第 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);
 }

 

posted on 2022-12-03 18:50  towboat  阅读(25)  评论(0)    收藏  举报