UVA 323 Jury Compromise

https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=259

题目

在一个遥远的国家,法庭上审判结果需要陪审团给出,陪审团是从大众中选出来的。首先从社会中随机抽取n个人,参与诉讼的控方和辩方会对每个人打分,0表示完全不赞同,20表示完全赞同。法官为了公平,会尽量均衡地从这n个人中选择m个人,使控方和辩方都比较满意。具体是:将选出的m个人的控方打分加起来,得到a,将选出的m个人的检方打分加起来,得到b,计算$\left\lvert a-b\right\rvert$。选择$\left\lvert a-b\right\rvert$最小的m人作为陪审团,如果同时存在多种选择,选择a+b最大的作为陪审团。写出程序,模拟选择的过程,并输出选择的方案。

$1\leqslant n\leqslant 200, 1\leqslant m\leqslant 20$

题解

设$dp[a][i][j]$为前$a$个人选择了i个人,差为j

$dp[a][i][j]=dp[a-1][i][j]$

$dp[a][i][j]=dp[a-1][i-1][j-(p-q)]+a[p]+a[q]$

计算值的时候可以滚动优化掉第一维,转移的时候需要完整记录

AC代码

#include<cstdio>
#include<cstring>
#define REP(i,a,b) for(register int i=(a); i<(b); i++)
#define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
#define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
using namespace std;
typedef long long ll;
int dp[27][807];
int pj[207][27][807], pa[207][27][807];
bool can[27][807];
int p[207], d[207];
int n,m;
void prn(int a, int i, int j) {
	if(i==0) return;
	int ka = pa[a][i][j];
	prn(ka-1, i-1, pj[ka][i][j]);
	printf(" %d", ka);
}
int main() {
	int kase=0;
	while(~scanf("%d%d", &n, &m) && n) {
	REPE(i,1,n) {
		scanf("%d%d", &p[i], &d[i]);
	}
	memset(can,0,sizeof can), memset(dp,-1,sizeof dp);
	dp[0][400]=0, can[0][400]=1;
	//dp[a][i][j] = dp[a-1][i][j]
	//dp[a][i][j] = dp[a-1][i-1][j-(p[i]-d[i])]
	REPE(a,1,n) PERE(i,m,1) {
		REPE(j,0,800) {
			int pv=j-(p[a]-d[a]);
			pa[a][i][j]=pa[a-1][i][j];
			pj[a][i][j]=pj[a-1][i][j];
			if(pv<=800 && pv>=0 && can[i-1][pv]) {
				int nd=dp[i-1][pv]+p[a]+d[a];
				if(nd>dp[i][j]) {
					dp[i][j]=nd;
					can[i][j]=1;
					pj[a][i][j]=pv;
					pa[a][i][j]=a;
				}
			}
		}
	}
	int ans=-1, ch=-1;
	REPE(dj,0,400) {
		if(can[m][dj+400] && dp[m][dj+400]>ans) {
			ans=dp[m][dj+400];
			ch=dj+400;
		}
		if(can[m][400-dj] && dp[m][400-dj]>ans) {
			ans=dp[m][400-dj];
			ch=400-dj;
		}
		if(ch>=0) break;
	}
	printf("Jury #%d\n", ++kase);
	printf("Best jury has value %d for prosecution and value %d for defence:\n", (ans+ch-400)/2, (ans-ch+400)/2);
	prn(n, m, ch);
	putchar('\n');
	putchar('\n');
	}
}

猜你喜欢

转载自www.cnblogs.com/sahdsg/p/12426756.html