POJ-1015 Jury Compromise

简单说一下,动态规划,d[i][j]代表已选择i个人, P-D差值为j-400时,能取到的P+D最大和
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
const int N=800+10;
const int M=20+5;
const int fix=400; 
int d[M][N],f[M][N];
int a[N],b[N];
bool find(int u,int d,int t) //查找有没有用过k
{
	if(d==0) return true;
	if(f[d][u]==t) return false;
	while(d>0)
	{
		u-=a[f[d][u]];
		d--;
		if(d<=0) break;
		if(f[d][u]==t) return false;
	}
	return true;
}
int main()
{
	int n,m,kase=0,a0,b0;
	while(~scanf("%d%d",&n,&m))
	{
		if(n==0&&m==0) break;
		for(int i=0;i<n;i++)
		{
			scanf("%d%d",&a0,&b0);
			a[i]=a0-b0; //差值
			b[i]=a0+b0; //和值
		}
		memset(d,-1,sizeof(d));
		d[0][400]=0; //起始状态
		for(int i=0;i<m;i++)
		{
			for(int j=0;j<N;j++)
				if(d[i][j]!=-1)
				{
					for(int k=0;k<n;k++)
						if(find(j,i,k)) //没有被用过
						{
							if(d[i+1][j+a[k]]<d[i][j]+b[k]) 
							{
								d[i+1][j+a[k]]=d[i][j]+b[k]; //更新
								f[i+1][j+a[k]]=k; //记录使用的
							}
						}
				}
		}
		int s,ma,mb=0;
		for(int i=0;i<=fix;i++)
		{
			if(d[m][fix+i]!=-1)
			{
				ma=fix+i;
				mb=d[m][fix+i];
			}
			if(d[m][fix-i]!=-1&&d[m][fix-i]>mb)
			{
				ma=fix-i;
				mb=d[m][fix-i];
			}
			if(mb) break;
		}
		s=ma;
		ma-=fix;
		int sp[M],cnt=0;
		int t=m;
		sp[cnt++]=f[t][s]+1;
		while(t>0)
		{
			s-=a[f[t][s]];
			t--;
			if(t<=0) break;
			sp[cnt++]=f[t][s]+1;
		}
		int pro,def;
		pro=(mb-ma)/2+ma;
		def=mb-pro;
		printf("Jury #%d\n",++kase);
		printf("Best jury has value %d for prosecution and value %d for defence:\n",pro,def);
		sort(sp,sp+cnt);
		for(int i=0;i<cnt;i++)
			printf(" %d",sp[i]);
		printf("\n\n");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值