标签:
这道题目实在是没看懂,无奈百度了中文版。
题意:在一个不存在的国家,要举行不存在的审判,现在要选出合适的陪审团。一共有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。哎,别人家的程序。
标签:
原文地址:http://www.cnblogs.com/xuezhonghao/p/4761511.html