二维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; }