0%

poj1015 Jury Compromise

题意

简单来说,从n个人中挑m个人,每个人有两个评分,要求令评分差绝对值最小,评分差绝对值最小的情况下找总评分最大的

题解

这道题。。细节很多。。思路很简单的dp,dp[i][j]表示选了i个人评分差之和的绝对值为j,更新的方程就显而易见了,从i-1个人中可能的情况向后更新,这里面有不少问题,一个是你要怎么判断这个人有没有被选中,实际上考虑到这个数据量。。直接搜索即可,另外要注意一定找遍整个路径,不然的话很多数据更新时候的问题。。第二个是dp的顺序,一开始我是按每个人遍历整个dp数组然后下一个人,但是这样会导致一个人被反复用的情况。。所以我换了一下思路。。第二个要输出选的人 升序输出。。反正输出格式化是蛮费事的。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
struct people{
int score[2],sum,sub;
}person[230];
int dp[22][820],last[22][820];
void input(int i){
scanf("%d%d",&person[i].score[0],&person[i].score[1]);
person[i].sub=person[i].score[0]-person[i].score[1];
person[i].sum=person[i].score[0]+person[i].score[1];
}
bool select(int j,int t,int i){
while(last[j][t]!=-1){
if(last[j][t]==i){
return false;
}
t-=person[last[j][t]].sub;
j--;
}
return true;
}
int main(){
int n,m;
int T=1;
while(scanf("%d%d",&n,&m),n+m){
memset(dp,-1,sizeof(dp));
memset(last,-1,sizeof(last));
dp[0][400]=0;
for(int i=0;i<n;++i){
input(i);
}
for(int j=0;j<m;++j){
for(int i=0;i<n;++i){
for(int t=0;t<=800;++t){
if(dp[j][t]!=-1&&select(j,t,i)){
if((dp[j][t]+person[i].sum)>dp[j+1][t+person[i].sub]){
dp[j+1][t+person[i].sub]=dp[j][t]+person[i].sum;
last[j+1][t+person[i].sub]=i;
}
}
}
}
}
int ansmax=0,res[2]={0,0},ans;
bool find=false;
for(int i=0;i<=400;++i){
if(dp[m][400+i]!=-1){
ansmax=dp[m][400+i],ans=400+i;
find=true;
}
if(dp[m][400-i]!=-1){
if(dp[m][400-i]>ansmax){
ansmax=dp[m][400-i],ans=400-i;
find=true;
}
}
if(find){
break;
}
}
int index=m;
vector<int> resque;
while(last[index][ans]!=-1){
int i=last[index][ans];
resque.push_back(i);
res[0]+=person[i].score[0],res[1]+=person[i].score[1];
index--,ans-=person[i].sub;
}
sort(resque.begin(),resque.end());
printf("Jury #%d\n",T);
T++;
printf("Best jury has value %d for prosecution and value %d for defence:\n",res[0],res[1]);
for(int i=0;i<resque.size();++i){
printf(" %d",resque[i]+1);
}
printf("\n\n");
}
return 0;
}