陪审团

当一个背包有两个维度的价值的时候 可以考虑把价值压到状态里
这道题记录绝对值的话没有办法唯一确定价值 所以要记录差值
为了保证数组下标始终为正 所以我们要加上偏移量

在记录路径的时候 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的值要保证不能修改 这样到最后才便于判断
//技巧: 将偏移的量给封装起来

posted @ 2022-02-09 16:32  __iostream  阅读(76)  评论(0)    收藏  举报