POJ 1015 Jury Compromise

感觉此题略难。。。。。。

背包问题。据说有一种二维DP的写法是错的。亲测,背包做法无误。

dp[i][j][k]表示前i个物品,选择j个,差值为k的情况下获得的最大总和

dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-1][k-差]+和) 即第i个物品用或者不用。

DP完成之后,在表中寻找一下最优解即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;

struct Path
{
  //  int a,b,c;
    int w;
} path[200+20][20+20][1000+20];
int dp[200+20][20+20][1000+20];
int p[200+20],d[200+20];
int n,m;
stack<int>S;
int Z=400;

int main()
{
    int Case=1;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m) break;

        for(int i=1; i<=n; i++) scanf("%d%d",&p[i],&d[i]);
        memset(dp,-1,sizeof dp);
        dp[0][0][Z]=0;

        for(int i=0; i<=n; i++)
            for(int j=0; j<=m; j++)
                for(int k=0; k<=2*Z; k++)
                    path[i][j][k].w=-1;

        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<=m; j++)
            {
                for(int k=Z*2; k-(p[i]-d[i])>=0; k--)
                {
                    if(dp[i-1][j][k]!=-1)
                    {
                        dp[i][j][k]=dp[i-1][j][k];
                        path[i][j][k].w=0;
                    }

                    if(j>=1&&dp[i-1][j-1][k-(p[i]-d[i])]!=-1)
                    {
                        if(dp[i-1][j-1][k-(p[i]-d[i])]+p[i]+d[i]>dp[i][j][k])
                        {
                            dp[i][j][k]=dp[i-1][j-1][k-(p[i]-d[i])]+p[i]+d[i];
                            path[i][j][k].w=1;
                        }
                    }
                }
            }
        }

        int posa,posb,posc;
        int Max=-1;
        for(int i=0; i<=Z; i++)
        {
            for(int j=1; j<=n; j++)
                if(dp[j][m][Z+i]>Max&&path[j][m][Z+i].w==1)
                    Max=dp[j][m][Z+i],posa=j,posb=m,posc=Z+i;
            for(int j=1; j<=n; j++)
                if(dp[j][m][Z-i]>Max&&path[j][m][Z-i].w==1)
                    Max=dp[j][m][Z-i],posa=j,posb=m,posc=Z-i;
            if(Max!=-1) break;
        }

        while(!S.empty()) S.pop();

        int ans1,ans2;
        ans1=(posc-Z+dp[posa][posb][posc])/2;
        ans2=ans1-(posc-Z);

        while(1)
        {
            if(path[posa][posb][posc].w==-1) break;
            if(path[posa][posb][posc].w!=-1)
            {
                int Newa,Newb,Newc;
                if(path[posa][posb][posc].w==1)
                {
                    S.push(posa);
                    Newa=posa-1;
                    Newb=posb-1;
                    Newc=posc-(p[posa]-d[posa]);
                }
                else
                {
                    Newa=posa-1;
                    Newb=posb;
                    Newc=posc;
                }
                posa=Newa;
                posb=Newb;
                posc=Newc;
            }
        }

        printf("Jury #%d\n",Case++);
        printf("Best jury has value %d for prosecution and value %d for defence:\n",ans1,ans2);
        while(!S.empty())
        {
            printf(" %d",S.top());
            S.pop();
        }
        printf("\n\n");

    }
    return 0;
}

 

posted @ 2016-01-21 17:42  Fighting_Heart  阅读(179)  评论(0编辑  收藏  举报