Jury Compromise POJ - 1015
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jury Compromise POJ - 1015相关的知识,希望对你有一定的参考价值。
题意:
在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团。选m人的办法是: 控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0到20。为了公平起见,法官选出陪审团的原则是:选出的m个人,必须满足辩方总分和控方总分的差的绝对值最小。如果有多种选择方案的辩方总分和控方总分的之差的绝对值相同,那么选辩控双方总分之和最大的方案即可。
题解:
p为辩方分数,d为控方分数
我们将p-d设为体积,p+d设为价值
设dp[i][j][k]:表示在前i个人中选择了j个人,差值为k,k的范围是[-400,400],数组不能出现负下标,所以我们用[0,800]代替,base=400
转移方程:
dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-1][k-(a[i]-b[i])]+a[i]+b[i])
题目要求求出最小差值,所以转移完方程后,我们这样找最小值,差值一样要总和更大的
while(dp[n][m][base-v]<0&&dp[n][m][base+v]<0) v++;
if(dp[n][m][base-v]>dp[n][m][base+v]){
v=base-v;
}
else v=base+v;
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int a[210],b[210],c[210];
int dp[210][22][810];
int n,m,base=400;
int main() {
int k=1;
while(cin>>n>>m){
if(n==m&&m==0) break;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
}
cout<<"Jury #"<<k++<<endl;
memset(dp,-0x3f,sizeof(dp));
dp[0][0][base]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=800;k++) {
dp[i][j][k]=dp[i-1][j][k];
int t=k-(a[i]-b[i]);
if(t<0||t>800||j<1) continue;
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][t]+a[i]+b[i]);
}
//寻找最小的差值,v表示的就是差值
int v=0;
while(dp[n][m][base-v]<0&&dp[n][m][base+v]<0) v++;
if(dp[n][m][base-v]>dp[n][m][base+v]){
v=base-v;
} else v=base+v;
int i=n,j=m,cnt=0,s1=0,s2=0;
//倒着推,确定由谁转移而来
while(j){
if(dp[i][j][v]==dp[i-1][j][v]) i--;
else {
c[cnt++]=i;
s1+=a[i];
s2+=b[i];
v-=(a[i]-b[i]);
i--;j--;
}
}
cout<<"Best jury has value "<<s1<<" for prosecution and value "<<s2<<" for defence:"<<endl;
sort(c,c+cnt);
for(int i=0;i<cnt-1;i++) cout<<c[i]<<' ';
cout<<c[cnt-1]<<endl<<endl;
}
return 0;
}
以上是关于Jury Compromise POJ - 1015的主要内容,如果未能解决你的问题,请参考以下文章
[kuangbin 基础dp][POJ 1015] Jury Compromise(dp)