In Frobnia, a far-away country, the verdicts in court trials are determined by a jury consisting of members of the general public. Every time a trial is set to begin, a jury has to be selected, which is done as follows. First, several people are drawn randomly from the public. For each person in this pool, defence and prosecution assign a grade from 0 to 20 indicating their preference for this person. 0 means total dislike, 20 on the other hand means that this person is considered ideally suited for the jury.
Based on the grades of the two parties, the judge selects the jury. In order to ensure a fair trial, the tendencies of the jury to favour either defence or prosecution should be as balanced as possible. The jury therefore has to be chosen in a way that is satisfactory to both parties.
We will now make this more precise: given a pool of n potential jurors and two values di (the defence's value) and pi (the prosecution's value) for each potential juror i, you are to select a jury of m persons. If J is a subset of {1,..., n} with m elements, then D(J ) = sum(dk) k belong to J
and P(J) = sum(pk) k belong to J are the total values of this jury for defence and prosecution.
For an optimal jury J , the value |D(J) - P(J)| must be minimal. If there are several jurys with minimal |D(J) - P(J)|, one which maximizes D(J) + P(J) should be selected since the jury should be as ideal as possible for both parties.
You are to write a program that implements this jury selection process and chooses an optimal jury given a set of candidates.
InputBased on the grades of the two parties, the judge selects the jury. In order to ensure a fair trial, the tendencies of the jury to favour either defence or prosecution should be as balanced as possible. The jury therefore has to be chosen in a way that is satisfactory to both parties.
We will now make this more precise: given a pool of n potential jurors and two values di (the defence's value) and pi (the prosecution's value) for each potential juror i, you are to select a jury of m persons. If J is a subset of {1,..., n} with m elements, then D(J ) = sum(dk) k belong to J
and P(J) = sum(pk) k belong to J are the total values of this jury for defence and prosecution.
For an optimal jury J , the value |D(J) - P(J)| must be minimal. If there are several jurys with minimal |D(J) - P(J)|, one which maximizes D(J) + P(J) should be selected since the jury should be as ideal as possible for both parties.
You are to write a program that implements this jury selection process and chooses an optimal jury given a set of candidates.
The input file contains several jury selection rounds. Each round starts with a line containing two integers n and m. n is the number of candidates and m the number of jury members.
These values will satisfy 1<=n<=200, 1<=m<=20 and of course m<=n. The following n lines contain the two integers pi and di for i = 1,...,n. A blank line separates each round from the next.
The file ends with a round that has n = m = 0.
OutputThese values will satisfy 1<=n<=200, 1<=m<=20 and of course m<=n. The following n lines contain the two integers pi and di for i = 1,...,n. A blank line separates each round from the next.
The file ends with a round that has n = m = 0.
For each round output a line containing the number of the jury selection round ('Jury #1', 'Jury #2', etc.).
On the next line print the values D(J ) and P (J ) of your jury as shown below and on another line print the numbers of the m chosen candidates in ascending order. Output a blank before each individual candidate number.
Output an empty line after each test case.
Sample InputOn the next line print the values D(J ) and P (J ) of your jury as shown below and on another line print the numbers of the m chosen candidates in ascending order. Output a blank before each individual candidate number.
Output an empty line after each test case.
4 2 1 2 2 3 4 1 6 2 0 0Sample Output
Jury #1 Best jury has value 6 for prosecution and value 4 for defence: 2 3Hint
If your solution is based on an inefficient algorithm, it may not execute in the allotted time.
哇,这道题是真的绕,简单说一下,方便我之后复习的时候快点想起来好了。
dp[i][k]表示有i个人并且D[I]-P[I]差值为k时的最大的D[I]+P[I],这里由于相减可能为负数,所以我们把D[I]-P[I]=0的情况改成D[I]-P[I]=m*20,相当于把坐标上的原点移一下,然后用dp[i][k]=max(dp[i-1][k-(d[i]-p[i])]+d[i]+p[i],dp[i][k]),来转移,但是要注意判定j之前是否加入过陪审团,并且判断dp[i-1][k-(d[i]-p[i])]是否能到达,下面贴代码,代码很乱,看的头晕,勉强AC
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[25][1000];
int path[25][1000];
int d[300],p[300];
int s[300],v[300];
int re[300];
int main(){
int m,n,tt=1;
while(scanf("%d%d",&n,&m)){
if(m==0&&n==0) break;
if(tt!=1) printf("\n");
memset(dp,-1,sizeof(dp));
memset(path,0,sizeof(path));
for(int i=1;i<=n;i++) {
scanf("%d%d",&d[i],&p[i]);
s[i]=d[i]-p[i];
v[i]=d[i]+p[i];
}
int mai=m*20;
dp[0][mai]=0;
for(int i=1;i<=m;i++){
for(int k=0;k<=mai*2;k++){
for(int j=1;j<=n;j++){
if(dp[i-1][k-s[j]]>=0){
if(dp[i][k]<dp[i-1][k-s[j]]+v[j]){
int t1=i-1;
int t2=k-s[j];
while(t1!=0){
if(path[t1][t2]==j) break;
t2=t2-s[path[t1][t2]];
t1--;
}
if(t1==0){
path[i][k]=j;
dp[i][k]=dp[i-1][k-s[j]]+v[j];
}
}
}
}
}
}
int tem=mai;
for(int i=0;i<=mai;i++){
if(dp[m][mai-i]==-1&&dp[m][mai+i]==-1)continue;
if(dp[m][mai-i]>dp[m][mai+i]){
int t1=m;
int t2=mai-i;
while(t1!=0){
re[t1-1]=path[t1][t2];
t2=t2-s[path[t1][t2]];
t1--;
}
}
else {
int t1=m;
int t2=mai+i;
while(t1!=0){
re[t1-1]=path[t1][t2];
t2=t2-s[path[t1][t2]];
t1--;
}
}
break;
}
int r1=0,r2=0;
for(int i=0;i<m;i++){
r1+=d[re[i]];
r2+=p[re[i]];
}
sort(re,re+m);
printf("Jury #%d \nBest jury has value %d for prosecution and value %d for defence: \n",tt++,r1,r2);
for(int i=0;i<m;i++) printf(" %d",re[i]);
printf("\n");
}
}
讲真,三层for循环居然没有LTE,而且最内层for循环里面还有一个判断是否加入的循环,感觉真是·····AC了就好,听说UVA 上面还有一个数据加强版的,我现在再去提交一下试试吧
更新:
上面代码有着很多的问题,UVA上的那道题并没有通过,之后又去看了其他的博客,发现是如果有两组有一些人相同的候选组的P[J]和D[J]相同,那么系统只会存储其中一组,这样是有一些问题的,看了其他博客之后进行了修改,直接按照每个人是否进入候选组来看,完全变成了01背包问题,而且由于最终组的人确定之后和这个人是第几次加进来的没有关系,所有可以用01背包而没有错误
下面AC代码
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[25][1000];
int path[25][1000][30];
int d[300],p[300];
int s[300],v[300];
int re[300];
int main(){
int n,m,tt=1;
while(scanf("%d%d",&n,&m)){
if(n==0&&m==0) break;
memset(dp,-1,sizeof(dp));
memset(path,0,sizeof(path));
for(int i=1;i<=n;i++){
scanf("%d%d",&d[i],&p[i]);
s[i]=d[i]-p[i];
v[i]=d[i]+p[i];
}
int mai=m*20;
dp[0][mai]=0;
for(int i=1;i<=n;i++){
for(int j=m;j>0;j--){
for(int k=0;k<=2*mai;k++){
int temp=k+s[i];
if(temp<0) continue;
if(dp[j-1][temp]==-1) continue;
if(dp[j][k]<dp[j-1][temp]+v[i]){
dp[j][k]=dp[j-1][temp]+v[i];
for(int te=1;te<=j-1;te++){
path[j][k][te]=path[j-1][temp][te];
}
path[j][k][j]=i;
}
}
}
}
int rer;
for(int i=0;i<=mai;i++){
if(dp[m][mai+i]==-1&&dp[m][mai-i]==-1) continue;
// printf("!!%d\n",i);
if(dp[m][mai+i]>dp[m][mai-i]) {
rer=mai+i;
}
else{
rer=mai-i;
}
break;
}
int ans[30];
for(int i=1;i<=m;i++){
ans[i]=path[m][rer][i];
}
int red=0,rep=0;
for(int i=1;i<=m;i++){
red+=d[ans[i]];
rep+=p[ans[i]];
}
printf("Jury #%d\nBest jury has value %d for prosecution and value %d for defence:\n",tt++,red,rep);
for(int i=1;i<=m;i++){
printf(" %d",ans[i]);
}
printf("\n\n");
}
}