pku1015Jury Compromise-最小差最大和dp

pku1015Jury Compromise


n组数字,每组两个数字 d 和 p,要求从中选出m组,使(m个d的和)与(m个p的和)之差最大,如果有种情况的差值相同,取所有d,p总和最大的那种情况。


参考



#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int dp[21][801],path[21][801],v[201],s[201],list[21];

bool select(int j,int k,int i)
{
	while(j>0 && path[j][k]!=i)
	{
		k-=v[ path[j][k] ];
		j--;	
	}
	return j?1:0;
}

int main()
{
	int T=1,n,m,i,j,k,d,p,fix;
	while(scanf("%d%d",&n,&m),n+m)
	{
		memset(dp,-1,sizeof(dp));memset(path,0,sizeof(path));
		fix=m*20;dp[0][fix]=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&d,&p);
			v[i]=d-p;s[i]=d+p;
		}
		
		for(j=1;j<=m;j++)
			for(k=0;k<=2*fix;k++)
				if(dp[j-1][k]>=0)
					for(i=1;i<=n;i++)
						if(dp[j][k+v[i]]<dp[j-1][k]+s[i])
							if(!select(j-1,k,i))
							{
								dp[j][k+v[i]]=dp[j-1][k]+s[i];
								path[j][k+v[i]]=i;
							}
	//	for(i=1;i<=m;i++)	printf("!%d ",list[i]);printf("\npath\n");
		for(k=0;k<=fix;k++)
			if(dp[m][fix-k]>=0||dp[m][fix+k]>=0)	break;
		d=dp[m][fix-k]>dp[m][fix+k]?fix-k:fix+k;
		
		for(p=d,i=1;i<=m;i++)
		{
			list[i]=path[m-i+1][p];
			p-=v[list[i]];
		}
		sort(list+1,list+m+1);
		printf("Jury #%d\n",T++);
		printf("Best jury has value %d for prosecution and value %d for defence:\n",(dp[m][d]+d-fix)/2,(dp[m][d]-d+fix)/2);
		for(i=1;i<=m;i++)	printf(" %d",list[i]);printf("\n\n");
	}
	return 0;
}

/*
4 2 
1 2 
2 3 
4 1 
6 2 

Jury #1 
Best jury has value 6 for prosecution and value 4 for defence: 
 2 3 
*/





你可能感兴趣的:(pku1015Jury Compromise-最小差最大和dp)