poj1015 Jury Compromise

二维DP还挺好想吧,然而头皮发麻写的 不是很会输出方案的说。。

一开始像往常一样弄个返回的位置一步步退,结果发现后面还会更新到返回的地方,omg

%了题解发现是枚举m先,然后用z数组记录第i步选的是啥,最后for循环就退回去了。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>

#define f(i,j) FF[i][j+550]
#define z(i,j) ZZ[i][j+550]
using namespace std;

int d[210],p[210];
int FF[40][1100],ZZ[1100][1100];
int as[40];

int main()
{
    int n,m,T_T=0;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)break;
        
        printf("Jury #%d
",++T_T);
        for(int i=1;i<=n;i++)scanf("%d%d",&d[i],&p[i]);
        
        memset(FF,-1,sizeof(FF));f(0,0)=0;
        memset(ZZ,0,sizeof(ZZ));
        for(int i=0;i<m;i++)
            for(int j=-500;j<=500;j++)
                if(f(i,j)>=0)
                    for(int k=1;k<=n;k++)
                        if(f(i,j)+p[k]+d[k]>f(i+1,j+d[k]-p[k]))
                        {
                            int x=i,y=j;
                            while(x>0&&z(x,y)!=k)
                            {
                                y-=d[z(x,y)]-p[z(x,y)];
                                x--;
                            }
                            if(x==0)
                            {
                                f(i+1,j+d[k]-p[k])=f(i,j)+p[k]+d[k];
                                z(i+1,j+d[k]-p[k])=k;
                            }
                        }
                
        int j=0;
        while(f(m,j)==-1&&f(m,-j)==-1)j++;
        if(f(m,j)<f(m,-j))j=-j;
        printf("Best jury has value %d for prosecution and value %d for defence:
",(f(m,j)+j)/2,(f(m,j)-j)/2);
        for(int i=1;i<=m;i++)
        {
            as[i]=z(m-i+1,j);
            j-=d[as[i]]-p[as[i]];
        }
        sort(as+1,as+m+1);
        for(int i=1;i<=m;i++)printf(" %d",as[i]);
        printf("

");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/9455169.html