首页 > 代码库 > POJ1015

POJ1015

题目链接:http://poj.org/problem?id=1015

大概题意:

  法庭要挑选m人陪审团。先随机挑选n个公民,对于每个公民,控辩双方都有各自的“喜好度”p[ ] 和 d[ ],法庭要尽量保证陪审团的m人中控方总喜好度和辩方总喜好度的差值的绝对值尽可能小,如果最佳的结果有多个,那么就选择控辩双方总喜好度最高的那个。

解题思路:

  日常不会dp题,哭),。。。

  设一个二维数组 dp[i][j], i代表“使用”了几个人,j代表控辩双方喜好度之差,为了避免出现数组下标为负的情况,我们可以把j值的最后再加上20*m。

  状态转移方程:dp[i+1][j+dat] = min(dp[i+1][j+dat] , dp[i][j]+sum).具体细节看代码吧。

  Waring: 要把选取哪个人这个循环放在最外层,不然会出现这种bug: 比如说 dp[5][?] = {1,2,3,5,6} = {1,2,3,7,8},但是最优解是dp[6][?]={1,2,3,5,6,7}, 如果程序选取的是{1,2,3,5,6}..............待续

AC代码:

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 
 7 const int inf=0x7ffffff;
 8 int dp[22][808];
 9 pair<int,int> pd[202];
10 vector<int> path[22][808];
11 int main()
12 {
13 //    freopen("in.txt","r",stdin);
14 //    freopen("out.txt","w",stdout);
15     int n,m,a,b,cases=1,min_n;
16     while(scanf("%d%d",&n,&m)==2&&n&&m){
17         for(int i=1;i<=n;i++)
18             scanf("%d%d",&pd[i].first,&pd[i].second);
19         min_n=20*m;
20         for(int i=0;i<=m;i++){
21             for(int j=0;j<=40*m;j++){
22                 path[i][j].clear();
23                 dp[i][j]=-inf;
24             }
25         }
26         dp[0][min_n]=0;
27         for(int k=1;k<=n;k++){
28             int dat=pd[k].first-pd[k].second, sum=pd[k].first+pd[k].second;
29             for(int i=m-1;i>=0;i--){
30                 for(int j=0;j<=40*m;j++){
31                     if(dp[i][j]>=0){
32                         if(dp[i+1][j+dat]<=dp[i][j]+sum){
33                             dp[i+1][j+dat]=dp[i][j]+sum;
34                             path[i+1][j+dat]=path[i][j];
35                             path[i+1][j+dat].push_back(k);
36                         }
37                     }
38                 }
39             }
40         }
41         a=b=0;
42         for(int i=0;i<=20*m;i++){
43             if(dp[m][min_n+i]>=0||dp[m][min_n-i]>=0){
44                 int temp;
45                 if(dp[m][min_n+i]>dp[m][min_n-i])   temp=min_n+i;
46                 else    temp=min_n-i;
47                 for(int l=0;l<m;l++){
48                     int ind=path[m][temp][l];
49                     a+=pd[ind].first,b+=pd[ind].second;
50                 }
51                 printf("Jury #%d\n",cases++);
52                 printf("Best jury has value %d for prosecution and value %d for defence:\n",a,b);
53                 for(int l=0;l<m;l++)    printf(" %d",path[m][temp][l]);
54                 printf("\n\n");
55                 break;
56             }
57         }
58 
59     }
60     return 0;
61 }
View Code

 

POJ1015