1. 程式人生 > >POJ 1015 -- 陪審團人選

POJ 1015 -- 陪審團人選

-a set best special 存在 none 註意 一個 ostream

陪審團人選

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

 

POJ 1015 -- 陪審團人選