POJ-1015

这道题目实在是没看懂,无奈百度了中文版。

题意:在一个不存在的国家,要举行不存在的审判,现在要选出合适的陪审团。一共有N个候选人。而控辩双方都对这N个人有着自己的满意度(0~20之间)。陪审团总共需要M人,你的任务就是从M个人中挑出N个人,使得控方对这N个人的满意度之和与辩方对这N个人的满意度之和相差最小。如果有多种情况,就挑出双方满意度之和最大的。

另:输出时成员的序号为升序。

这题与01背包有关

  a[i][j].s 表示 如果总共需要i人,那么控辩双方总满意度只差为j+400时,双方总满意度之和的最大值。//+400是因为c++里的数组默认从0开始(已被Pascal嘲笑多次),j的范围是-400~400。

  a[i][j].m[] 用来储存实际选择的人,输出时用。//其实这是一种人傻内存多的方法

  man[x][0/1] 表示 第x+1(因为数组从0开始)个人的 双方满意度之差 / 双方满意度之和

 

  DP方程 a[i][j+man[x][0]].s > a[i-1][j].s + man[x][1] --> 更新a[i][j+man[x][0]

做题的时候看了一点别人的提示,没想到题目中仿佛仅仅是顺便提了一句的多种情况,却是DP的关键。数据小的题目总有一种声东击西的感觉。

另外想到20*800*200的循环时,一开始我是拒绝的。这也太大了吧。后来发现了第三重循环很少能进去后,才知道原来真的是这样解。

 

比较惊喜的是这题一次AC了。

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 
 4 struct point{
 5   int s; //sum
 6   int m[25];
 7 };
 8 
 9 point a[22][900]; // 400 +- xx
10 int man[210][2]; //sum prosecution-defence sum xx + xx
11 
12 bool can(point q, int k){
13   for(int i = 1; i <= q.m[0]; ++i)
14     if(q.m[i] == k) return false;
15   return true;
16 }
17 
18 int main(void)
19 {
20   int N, M, K = 0;
21   int x, y;
22   int ans;
23   scanf("%d%d", &N, &M);
24   while(N > 0){
25     for(int i = 0; i < N; ++i){
26       scanf("%d%d", &x, &y);
27       man[i][0] = x - y;
28       man[i][1] = x + y;
29     }
30     for(int i = 0; i <= 800; ++i)
31       for(int j = 0; j <= M; ++j)
32     a[j][i].s = -1;
33     a[0][400].s = 0;
34     a[0][400].m[0] = 0;
35     for(int i = 1; i <= M ; ++i)
36       for(int j = 0; j <= 800; ++j)
37     if(a[i-1][j].s >= 0)
38       for(int k = 0; k < N; ++k)
39         if(can(a[i-1][j], k) && (a[i-1][j].s + man[k][1] > a[i][j+man[k][0]].s)){
40           point& q = a[i][j+man[k][0]];
41           q = a[i-1][j];
42           q.s += man[k][1];
43           q.m[++q.m[0]] = k;
44         }
45     for(x = 0; x <= 400; ++x)
46       if((a[M][400+x].s >= 0) || (a[M][400-x].s >= 0)) break;
47     ans = a[M][400+x].s > a[M][400-x].s ? 400+x : 400-x;
48     printf("Jury #%d \n", ++K);
49     printf("Best jury has value %d for prosecution and value %d for defence: \n", (a[M][ans].s+ans-400)/2, (a[M][ans].s-ans+400)/2);
50     std::sort(a[M][ans].m+1, a[M][ans].m+a[M][ans].m[0]+1);
51     for(int i = 1; i <= a[M][ans].m[0]; ++i)
52       printf(" %d", a[M][ans].m[i]+1);
53     printf(" \n\n");
54     scanf("%d%d", &N, &M);
55   }
56   return 0;
57 }

1.方便快捷的struct导致我无法用更加方便快捷的memset了

2.原来放弃iostream using namespace std后,sort就不好使了,需要改成std::sort();

3.我的程序2118kRAM,125MS,人家的程序388kRAM16MS。哎,别人家的程序。

posted on 2015-08-26 20:03  AlanXue  阅读(218)  评论(0编辑  收藏  举报

导航