poj1015Jury Compromise(动态规划+思维)

题解:令p-d为体积,p+d为价值;

定义状态转移方程:dp[i][j][k]:从前i个人里选j个人其差值为k; 令【-400,0】用【0,400】表示;【0,400】用【400,800】表示;

偏移量base=400;接下来就是01背包了,dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-1][k-(a[i]-b[i])]+a[i]+b[i]);

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
void io() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); }
int a[210],b[210],c[210];
int dp[210][22][810];
int n,m,base=400;
int main() {
    io(); 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]);
                }
        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;
}

猜你喜欢

转载自blog.csdn.net/qq_44132777/article/details/105981631