首页 > 代码库 > POJ 1015 -- 陪审团人选
POJ 1015 -- 陪审团人选
陪审团人选
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 29543 | Accepted: 7849 | Special Judge |
试题描述
在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团。选m人的办法是:
控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0到20。为了公平起见,法官选出陪审团的原则是:选出的m个人,必须满足辩方总分和控方总分的差的绝对值最小。如果有多种选择方案的辩方总分和控方总分的之差的绝对值相同,那么选辩控双方总分之和最大的方案即可。
输入
输入包含多组数据。每组数据的第一行是两个整数n和m,n是候选人数目,m是陪审团人数。注意,1<=n<=200, 1<=m<=20 而且 m<=n。接下来的n行,每行表示一个候选人的信息,它包含2个整数,先后是控方和辩方对该候选人的打分。候选人按出现的先后从1开始编号。两组有效数据之间以空行分隔。最后一组数据n=m=0
输出
对每组数据,先输出一行,表示答案所属的组号,如 ‘Jury #1‘, ‘Jury #2‘, 等。接下来的一行要象例子那样输出陪审团的控方总分和辩方总分。再下来一行要以升序输出陪审团里每个成员的编号,两个成员编号之间用空格分隔。每组输出数据须以一个空行结束。
样例输入
4 2 1 2 2 3 4 1 6 2 0 0
样例输出
Jury #1 Best jury has value 6 for prosecution and value 4 for defence: 2 3
答题思路:是一道有些奇怪的dp。因为题目中需要考虑的量较多,需要借助二维数组把多个量联系起来。具体见注释。
1 #include <iostream> 2 using namespace std; 3 4 int p[201],d[201],result[21]; 5 int dp[21][801],path[21][801]; 6 7 int cmp(const void *a,const void *b) //qsort 8 { 9 return *(int *)a-*(int *)b;10 }11 12 bool select(int a,int b,int i)//判断当前i在之前有没有用过 13 { 14 while(a>0 && path[a][b]!=i)15 {16 b-=p[path[a][b]]-d[path[a][b]];17 a--;18 }19 return (a!=0)?true:false;20 }21 22 int main()23 {24 int i,j,k,a,b,n,m,origin,ca=1;25 while(scanf("%d %d",&n,&m),n||m)26 {27 for(i=1;i<=n;i++)28 scanf("%d %d",p+i,d+i);29 memset(dp,-1,sizeof(dp));30 memset(path,0,sizeof(path));31 origin=m*20; //防止出现负数 32 for(dp[0][origin]=j=0;j<m;j++)33 for(k=0;k<=origin*2;k++) //*2同样是防止出现负数 34 if(dp[j][k]>=0)35 { //如果存在选j个人 ,差为k 36 for(i=1;i<=n;i++)37 if(dp[j+1][k+p[i]-d[i]]<dp[j][k]+p[i]+d[i])38 { //在总分的差相同时,如果当前已储存的j+1个人的总和比较小,就更新 39 a=j,b=k;40 if(!select(a,b,i))41 {42 dp[j+1][k+p[i]-d[i]]=dp[j][k]+p[i]+d[i];43 path[j+1][k+p[i]-d[i]]=i; //记录路径 44 }45 }46 }47 for(i=origin,j=0;dp[m][i+j]<0 && dp[m][i-j]<0;j++); //光循环,不运行下面的语句(相当于 {}中没东西 )。此句话找到了第一个可取的 j,下面接着用 48 k=dp[m][i+j]>dp[m][i-j]?i+j:i-j;49 printf("Jury #%d\n",ca++);50 printf("Best jury has value %d for prosecution and value %d for defence:\n",(dp[m][k]+k-origin)/2, (dp[m][k]-k+origin)/2);51 for(i=1;i<=m;i++){ //倒退路径 52 result[i]=path[m-i+1][k];53 k-=p[result[i]]-d[result[i]];54 }55 qsort(result+1,m,sizeof(int),cmp); //result+1:目标数组开始地址;m:个数;sizeof(范围);cmp:指针 56 for(i=1;i<=m;i++)57 printf(" %d",result[i]);58 printf("\n");59 printf("\n");60 }61 //system("pause");62 return 0;63 }
POJ 1015 -- 陪审团人选
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。