OpenJudge 2979 陪审团的人选 / Poj 1015 Jury Compromise

1.链接地址:

http://bailian.openjudge.cn/practice/2979

http://poj.org/problem?id=1015

2.题目:

总Time Limit:
1000ms
Memory Limit:
65536kB
Description
在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团。选m人的办法是:

控 方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0到20。为了公平起见,法官选出陪审团的原则是:选出的m个人,必须满足辩方总分和控方总 分的差的绝对值最小。如果有多种选择方案的辩方总分和控方总分的之差的绝对值相同,那么选辩控双方总分之和最大的方案即可。
Input
输入包含多组数据。每组数据的第一行是两个整数n和m,n是候选人数目,m是陪审团人数。注意,1<=n<=200, 1<=m<=20 而且 m<=n。接下来的n行,每行表示一个候选人的信息,它包含2个整数,先后是控方和辩方对该候选人的打分。候选人按出现的先后从1开始编号。两组有 效数据之间以空行分隔。最后一组数据n=m=0
Output
对每组数据,先输出一行,表示答案所属的组号,如 'Jury #1', 'Jury #2', 等。接下来的一行要象例子那样输出陪审团的控方总分和辩方总分。再下来一行要以升序输出陪审团里每个成员的编号,两个成员编号之间用空格分隔。每组输出数据须以一个空行结束。
Sample Input
4 2 
1 2 
2 3 
4 1 
6 2 
0 0 
Sample Output
Jury #1 
Best jury has value 6 for prosecution and value 4 for defence: 
 2 3 
Source
Southwestern European Regional Contest 1996, POJ 1015, 程序设计实习2007

3.思路:

这题自己没想到思路,参照了《程序设计导引及在线实践》的思路

动态规划题目,使用深度搜索的话会超时

4.代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 
  6 using namespace std;
  7 
  8 const int maxDiff = 400;
  9 
 10 int cmp(const void* a,const void *b)
 11 {
 12     int int_a = *((int *)a);
 13     int int_b = *((int *)b);
 14 
 15     return int_a - int_b;
 16 }
 17 
 18 int main()
 19 {
 20     //freopen("C://input.txt","r",stdin);
 21 
 22     int i,j,k;
 23     int temp;
 24     int temp_path,temp_diff;
 25 
 26     int n,m;
 27     cin >> n >> m;
 28 
 29     int count = 1;
 30     while(n != 0 || m != 0)
 31     {
 32         int *arr_sum = new int[n];
 33         int *arr_diff = new int[n];
 34 
 35         bool *arr_used = new bool[n];
 36         memset(arr_used,0,sizeof(bool) * n);
 37 
 38         int int_a,int_b;
 39         for(i = 0; i < n; ++i)
 40         {
 41             cin >> int_a >> int_b;
 42             arr_sum[i] = int_a + int_b;
 43             arr_diff[i] = int_a - int_b;
 44         }
 45 
 46         int **dp = new int*[m];
 47         for(i = 0; i < m; ++i)
 48         {
 49             dp[i] = new int[maxDiff * 2 + 1];
 50             for(j = 0; j <= maxDiff * 2; ++j) dp[i][j] = -1;
 51         }
 52 
 53         int **path = new int*[m];
 54         for(i = 0; i < m; ++i) path[i] = new int[maxDiff * 2 + 1];
 55 
 56         for(i = 0; i < n; ++i)
 57         {
 58             temp = arr_diff[i] + maxDiff;
 59             if(dp[0][temp] < arr_sum[i])
 60             {
 61                 dp[0][temp] = arr_sum[i];
 62                 path[0][temp] = i;
 63             }
 64 
 65             //cout << "dp[0][" << temp << "]="  << dp[0][temp] << "path[0][" << temp << "]=" << path[0][temp] << endl;
 66         }
 67 
 68 
 69         for(i = 1; i < m; ++i)
 70         {
 71             for(j = 0; j <= maxDiff * 2; ++j)
 72             {
 73                 if(dp[i - 1][j] != -1)
 74                 {
 75 
 76                     temp_diff = j;
 77                     for(k = i - 1; k >= 0; --k)
 78                     {
 79                         temp_path = path[k][temp_diff];
 80                         arr_used[temp_path] = true;
 81                         temp_diff = temp_diff - arr_diff[temp_path];
 82                     }
 83 
 84                     for(k = 0; k < n; ++k)
 85                     {
 86                         if(!arr_used[k])
 87                         {
 88                             temp = j + arr_diff[k];
 89                             if(dp[i][temp] == -1 || (dp[i][temp] < dp[i - 1][j] + arr_sum[k]))
 90                             {
 91                                 dp[i][temp] = dp[i - 1][j] + arr_sum[k];
 92                                 path[i][temp] = k;
 93                             }
 94                         }
 95                     }
 96 
 97 
 98                     temp_diff = j;
 99                     for(k = i - 1; k >= 0; --k)
100                     {
101                         temp_path = path[k][temp_diff];
102                         arr_used[temp_path] = false;
103                         temp_diff = temp_diff - arr_diff[temp_path];
104                     }
105                 }
106             }
107 
108         }
109 
110         int res_idx;
111         for(i = 0; i <= maxDiff; ++i)
112         {
113             if(dp[m - 1][maxDiff - i] != -1 || dp[m - 1][maxDiff + i] != -1)
114             {
115                 if(dp[m - 1][maxDiff - i] == -1) res_idx = i;
116                 else if(dp[m - 1][maxDiff + i] == -1) res_idx = - i;
117                 else
118                 {
119                     res_idx = (dp[m - 1][maxDiff + i] > dp[m - 1][maxDiff - i] ? i : (-i));
120                 }
121                 break;
122             }
123         }
124 
125         cout << "Jury #" << count++ << endl;
126         cout << "Best jury has value " << (dp[m - 1][res_idx + maxDiff] + res_idx) / 2<< " for prosecution and value " << (dp[m - 1][res_idx + maxDiff] - res_idx) / 2<< " for defence:" << endl;
127 
128         temp_diff = res_idx + maxDiff;
129         int *arr_res = new int[m];
130         for(i = m - 1; i >= 0; --i)
131         {
132             temp_path = path[i][temp_diff];
133             arr_res[i] = temp_path + 1;
134             temp_diff = temp_diff - arr_diff[temp_path];
135         }
136         qsort(arr_res,m,sizeof(int),cmp);
137 
138         for(i = 0; i < m; ++i) cout << " " << arr_res[i];
139         cout << endl;
140 
141         delete [] arr_res;
142 
143         cout << endl;
144 
145         delete [] arr_sum;
146         delete [] arr_diff;
147         
148         for(i = 0; i < m; ++i) delete [] dp[i];
149         delete [] dp;
150 
151 
152 
153         for(i = 0; i < m; ++i) delete [] path[i];
154         delete [] path;
155 
156         cin >> n >> m;
157     }
158 
159     return 0;
160 }

 

转载于:https://www.cnblogs.com/mobileliker/p/3577263.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值