陪审团
当一个背包有两个维度的价值的时候 可以考虑把价值压到状态里
这道题记录绝对值的话没有办法唯一确定价值 所以要记录差值
为了保证数组下标始终为正 所以我们要加上偏移量
在记录路径的时候 G不能够省去第一维度了 否则的话记录的只是最后一层从哪里来 就会出错
G只是纯粹的记录从哪里来 不存在递推的关系
#include <iostream>
#include <cstdio>
#include <cstring>
#define pa pair<int,int>
#define mp make_pair
#define fs first
#define sc second
#define F(j,k) f[(j)][(k)+400]
#define G(i,j,k) g[(i)][(j)][(k)+400]
using namespace std;
const int N=205;
const int M=25;
const int _INF=0xcfcfcfcf;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int h[N],num,a[N],b[N];
int n,m,test;
int f[M][805];
pa g[N][M][805];
void print(int x,int y,int z,pa p)
{
if(!x) return;
print(x-1,p.fs,p.sc,G(x-1,p.fs,p.sc));
if(p.fs==y-1) h[++num]=x;
}
int main()
{
while( (n=read())&&(m=read()))
{
memset(f,0xcf,sizeof f);
F(0,0)=0;num=0;
for(int i=1;i<=n;i++)
{
int x=read(),y=read();
a[i]=x+y; b[i]=x-y;
}
for(int i=1;i<=n;i++)
for(int j=min(i,m);j>=1;j--)
for(int k=-400;k<=400;k++)
{
G(i,j,k)=mp(j,k);
if(k-b[i]>=-400&&k-b[i]<=400&&F(j,k)<F(j-1,k-b[i])+a[i])
{
if(F(j-1,k-b[i])==_INF) continue;
F(j,k)=F(j-1,k-b[i])+a[i],G(i,j,k)=mp(j-1,k-b[i]);
}
}
printf("Jury #%d\n",++test);
int tmp=0;
for(int i=0;i<=400;i++)
if(F(m,i)!=_INF||F(m,-i)!=_INF)
{
F(m,i)>F(m,-i)?print(n,m,i,G(n,m,i)):print(n,m,-i,G(n,m,-i));
break;
}
int ans1=0,ans2=0;
for(int i=1;i<=num;i++) ans1+=(a[h[i]]+b[h[i]])/2,ans2+=(a[h[i]]-b[h[i]])/2;
printf("Best jury has value %d for prosecution and value %d for defence:\n",ans1,ans2);
for(int i=1;i<=num;i++) printf(" %d",h[i]);
puts("\n");
}
return 0;
}
//注意: inf的值要保证不能修改 这样到最后才便于判断
//技巧: 将偏移的量给封装起来

浙公网安备 33010602011771号