思路:背包类DP
提交:3次
错因:没有注意得分的上下界导致 RE 显示 WA
题解:
我们很容易的想到把两种分数做一个差,来尽量背到 (0) 。
那最大化总分呢?这时我们可以用两种分数的和作为物品的价值。
记录方案呢?每个状态开一个 vector ,来记录转移的物品。(今天新学)(虽然空间大但是方便写)
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
} const int N=810;
int T,n,m,cas,D,f[25][N],v[N/4],w[N/4];
vector <int> h[25][N];
inline void main() {
while(~scanf("%d%d",&n,&m)&&n) { memset(f,-1,sizeof f);
for(R i=1;i<=m;++i) for(R j=0;j<N;++j) h[i][j].clear(); D=20*m,f[0][D]=0;
for(R i=1,a,b;i<=n;++i) a=g(),b=g(),v[i]=a-b,w[i]=a+b;
for(R i=1;i<=n;++i) for(R j=m;j;--j) for(R k=max(0,v[i]),lim=2*D+min(0,v[i]);k<=lim;++k) //之前就是 k 的上界写错了。
if(~f[j-1][k-v[i]]) if(f[j-1][k-v[i]]+w[i]>f[j][k])
f[j][k]=f[j-1][k-v[i]]+w[i],h[j][k]=h[j-1][k-v[i]],h[j][k].push_back(i);
R sum; for(sum=0;sum<=D;++sum) if((~f[m][D+sum])||(~f[m][D-sum])) break;
R ans=f[m][D+sum]>f[m][D-sum]?D+sum:D-sum;
R anss=f[m][ans]; R ans1=(anss+(ans-D))/2,ans2=(anss-(ans-D))/2;
printf("Jury #%d
",++T);
printf("Best jury has value %d for prosecution and value %d for defence:
",ans1,ans2);
for(R i=0;i<m;++i) printf(" %d",h[m][ans][i]); printf("
");
}
}
} signed main() {Luitaryi::main(); return 0;}
2019.09.18
58