第 i个人的得分分别记为 a[i] 和 b[i]
m个人必须满足:辩方总分S(a) 和控方总分 S(b) 的差的绝对值最小
如果选择方法不唯一,那么再从中选择辨控双方总分之和最大的方案。
求最终的陪审团获得的辩方总分 D 控方总分 P, 以及陪审团人选的编号
吧这个绝对值的差的和作为状态
f[ i ] [j ] [ c] =min(f[i-1][j][c], f[i-1][j-1][ c-a[i]+b[i] ] +a[i]+b[i]
#include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define D 400 int n,m,a[202],b[202]; int f[202][25][802],pre[202][25][900]; int S1,S2; vector<int> vec; void print(int i,int j,int k){ if(j==0) return ; int p=pre[i][j][k]; print(p-1,j-1,k-a[p]+b[p]); vec.push_back(p); S1+=a[p],S2+=b[p]; } void solve(int cas){ memset(f,-0x3f,sizeof f);f[0][0][0+D]=0; int i,j; for(i=1;i<=n;i++) cin>>b[i]>>a[i]; for(i=1;i<=n;i++) for(j=m;j>=0;j--){ for(int k=-400;k<=400;k++){ f[i][j][D+k]=f[i-1][j][D+k]; pre[i][j][k+D]=pre[i-1][j][D+k]; if(k-a[i]+b[i]>=-400&&k-a[i]+b[i]<=400&&j>0){ if(f[i][j][k+D]<f[i-1][j-1][D+k-a[i]+b[i]]+a[i]+b[i]) f[i][j][D+k]=f[i-1][j-1][D+k-a[i]+b[i]]+a[i]+b[i], pre[i][j][k+D]=i; } } } j=0; for(i=0;i<=400;i++) if(f[n][m][i+400]>=0&&f[n][m][i+400]>f[n][m][400-i]){ j=i+400;break; } else if(f[n][m][400-i]>=0){ j=400-i;break;} vec.clear(); S1=S2=0; print(n,m,j); printf("Jury #%d\n",cas); printf("Best jury has value %d for prosecution and value %d for defence:", S2,S1); cout<<endl; for(i=0;i<vec.size();i++) cout<<vec[i]<<' '; cout<<"\n\n"; } main(){ int cas=0; while(cin>>n>>m,n&&m) solve(++cas); }