poj1015 2010.3.5
Poj 1015
【关键字】
动态规划
【摘要】
【正文】
1、题目描述
Jury Compromise
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 13023 Accepted: 3316 Special Judge
Description
In Frobnia, a far-away country, theverdicts in court trials are determined by a jury consisting of members of thegeneral 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 thepublic. For each person in this pool, defence and prosecution assign a gradefrom 0 to 20 indicating their preference for this person. 0 means totaldislike, 20 on the other hand means that this person is considered ideallysuited for the jury.
Based on the grades of the two parties, thejudge selects the jury. In order to ensure a fair trial, the tendencies of thejury 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 bothparties.
We will now make this more precise: given apool of n potential jurors and two values di (the defence's value) and pi (theprosecution's value) for each potential juror i, you are to select a jury of mpersons. If J is a subset of {1,..., n} with m elements, then D(J ) = sum(dk) kbelong to J
and P(J) = sum(pk) k belong to J are thetotal 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 asideal as possible for both parties.
You are to write a program that implementsthis jury selection process and chooses an optimal jury given a set ofcandidates.
Input
The input file contains several juryselection rounds. Each round starts with a line containing two integers n andm. 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 twointegers pi and di for i = 1,...,n. A blank line separates each round from thenext.
The file ends with a round that has n = m =0.
Output
For each round output a line containing thenumber of the jury selection round ('Jury #1', 'Jury #2', etc.).
On the next line print the values D(J ) andP (J ) of your jury as shown below and on another line print the numbers of them chosen candidates in ascending order. Output a blank before each individualcandidate number.
Output an empty line after each test case.
SampleInput
4 2
1 2
2 3
4 1
6 2
0 0
SampleOutput
Jury #1
Best jury has value 6 for prosecution andvalue 4 for defence:
2 3
Hint
If your solution is based on an inefficientalgorithm, it may not execute in the allotted time.
Source
Southwestern European Regional Contest 1996
2、算法分析
其实,这个状态转移方程,我真的没想出来,在网上搜了解题报告才知道原来是这么一回事,我还是太弱了。。。。
f[i][j][k], 表示前i个人, 已经选了j个人, 差值为k时, 得到的最大和.
3、源码
#include <stdio.h>
#include <string.h>
#define MAX 800+10
#define MAXN 200+10
#define MAXM 20+10
#define FLAG 400
#define X 20*m
int d[MAXN],p[MAXN],v[MAXN],s[MAXN],f[MAXN][MAXM][MAX],path[MAXN][MAXM][MAX],n,m,num=0;
void init()
{
int i;
for(i=1;i<=n;i++)
{
scanf("%d %d",&d[i],&p[i]);
v[i]=d[i]-p[i];
s[i]=d[i]+p[i];
}
}
int min(int a,int b)
{
if (a>b) return b;
else return a;
}
void dpit()
{
int i,j,k;
int st=-X,ed=X;
for(i=0;i<=n;++i)
for(j=0;j<=m;++j)
for(k=st;k<=ed;++k)
f[i][j][k+FLAG]=-1;
f[0][0][FLAG+0]=0;
for(i=1;i<=n;++i)
for(j=0;j<=min(i,m);++j)
for(k=st;k<=ed;++k)
{
f[i][j][k+FLAG]=f[i-1][j][k+FLAG];
path[i][j][k+FLAG]=1;
if ((j>=1)&&(k+v[i]>=-FLAG)&&(k+v[i]<=FLAG)&&(f[i-1][j-1][k+v[i]+FLAG]!=-1)&&(f[i-1][j-1][k+v[i]+FLAG]+s[i]>f[i][j][k+FLAG]))
{
f[i][j][k+FLAG]=f[i-1][j-1][k+v[i]+FLAG]+s[i];
path[i][j][k+FLAG]=2;
}
}
}
void print(int i,int j,int k)
{
if ((i==0) && (j==0) && (k==0)) return ;
if (path[i][j][k+FLAG]==1)
print(i-1,j,k);
else
{
print(i-1,j-1,k+v[i]);
printf(" %d",i);
}
}
void findit()
{
int ed=X;
int k;
for(k=0;k<=ed;++k)
{
if (f[n][m][k+FLAG]>f[n][m][-k+FLAG])
{
printf("Best jury has value %d for prosecution and value %d for defence:\n",(f[n][m][k+FLAG]-k)/2,(f[n][m][k+FLAG]+k)/2);
print(n,m,k);
break;
}
else
if (f[n][m][-k+FLAG]!=-1)
{
printf("Best jury has value %d for prosecution and value %d for defence:\n",(f[n][m][-k+FLAG]+k)/2,(f[n][m][-k+FLAG]-k)/2);
print(n, m, -k);
break;
}
}
}
int main()
{
while (scanf("%d %d",&n,&m),n)
{
num++;
init();
printf("Jury #%d\n",num);
dpit();
findit();
printf("\n");
printf("\n");
}
return 0;
}