标签:测试数据 print future 一个 scan always down 统计 ict
题目链接:http://poj.org/problem?id=1417
解题思路:比较容易想到的是并查集,然后把第三组数据测试一下之后发现这并不是简单的并查集,而是需要合并之后然后判断的。并且鉴于题目要求输出数据,因此还要记录数据,可以说是非常有意思的题目。
首先,如果a b yes,那么a与b一定都是圣人或者恶人;反之,如果a b no,那么两者一个圣人,一个恶人。因此可以将所有元素分为若干个集合,每个集合中放两个小集合,表示两种不一样的人,当然并不知道到底哪个里面是圣人,恶人。
另一个比较棘手的问题就是集合区分的情况,可以使用带权并查集,val[i]记录每个元素与祖先的关系,0为同种人,1为不同种人。那么在合并的时候就需要计算:val[ra] = (val[b] - val[a] + tmp + 2) % 2; 其中ra,rb为a,b的祖先,tmp表示a,b关系是yes -- 0, no -- 1。另外就是并查集find路径压缩的时候要更新val值。
还有一个问题就是DP了,可以这样:dp[i][j]表示前i个集合恰好选j个人圣人的方案数目,pre[i][j]则用来记录在背包i - 1处选择的人数,dp[bgcnt][p1]不为1的话输出no。
状态转移方程:
1 dp[0][0] = 1; 2 for(int i = 1; i <= bgcnt; i++){ 3 for(int j = 0; j <= p1; j++){ 4 if(j >= bagcnt[i][0] && dp[i - 1][j - bagcnt[i][0]]){ 5 dp[i][j] += dp[i - 1][j - bagcnt[i][0]]; 6 pre[i][j] = j - bagcnt[i][0]; 7 } 8 if(j >= bagcnt[i][1] && dp[i - 1][j - bagcnt[i][1]]){ 9 dp[i][j] += dp[i - 1][j - bagcnt[i][1]]; 10 pre[i][j] = j - bagcnt[i][1]; 11 } 12 } 13 }
整体步骤就比较好说了,大致就是:并查集合并--枚举每个人放入对应的集合,同时统计大小集合的人数--动态规划统计方案数目,同时记录从大集合选择的人数--逆序求每次选择的小集合并保存其所有元素--排序输出
整体过程比较复杂,写了好长时间,需要耐着性子。
另外给出一些测试数据,选择poj discuss块,感谢各位,如有不妥,敬请指出。
1 6 4 4 2 1 3 yes 3 1 5 no 4 6 6 yes 5 5 7 no 6 2 8 no 7 2 4 yes 8 9 6 6 2 10 1 3 yes 11 1 5 no 12 6 6 yes 13 5 7 no 14 2 8 no 15 2 4 yes 16 17 6 5 3 18 1 3 yes 19 1 5 no 20 6 6 yes 21 5 7 no 22 2 8 no 23 2 4 yes 24 0 0 1 25 26 27 1 1 0 28 1 1 yes 29 30 3 2 0 31 1 2 no 32 2 2 yes 33 1 1 yes 34 35 3 2 0 36 1 1 yes 37 2 2 yes 38 1 1 yes 39 40 7 4 2 41 2 3 no 42 3 4 no 43 4 3 no 44 5 5 yes 45 5 3 no 46 5 5 yes 47 1 5 yes 48 49 11 9 7 50 6 12 no 51 4 8 yes 52 3 12 yes 53 5 9 no 54 6 11 yes 55 6 5 no 56 15 4 yes 57 16 15 yes 58 10 3 no 59 6 16 no 60 2 6 no 61 6 2 4 62 1 1 yes 63 2 3 yes 64 3 4 yes 65 4 5 no 66 5 6 yes 67 6 6 yes 68 3 3 2 69 1 2 no 70 3 4 yes 71 3 5 no 72 73 0 0 0 74 75 输出: 76 no 77 1 78 2 79 3 80 4 81 6 82 7 83 end 84 no 85 end 86 1 87 end 88 no 89 1 90 2 91 end 92 1 93 2 94 4 95 5 96 end 97 no 98 5 99 6 100 end 101 no
代码:
1 const int maxm = 700; 2 int bagcnt[maxm][2]; 3 vector<int> bagele[maxm][2]; 4 int bgcnt; 5 int dp[maxm][maxm], pre[maxm][maxm]; 6 int fa[maxm], val[maxm], fb[maxm]; 7 int vis[maxm]; 8 int n, p1, p2, xn; 9 vector<int> anss; 10 11 void init(){ 12 xn = p1 + p2; 13 bgcnt = 0; 14 for(int i = 0; i <= xn; i++) { 15 fa[i] = i; 16 bagele[i][0].clear(); 17 bagele[i][1].clear(); 18 } 19 memset(val, 0, sizeof(val)); 20 memset(fb, 0, sizeof(fb)); 21 memset(bagcnt, 0, sizeof(bagcnt)); 22 memset(vis, 0, sizeof(vis)); 23 memset(dp, 0, sizeof(dp)); 24 memset(pre, 0, sizeof(pre)); 25 } 26 int find(int x){ 27 if(x ==fa[x]) return x; 28 int tmp = find(fa[x]); 29 val[x] += val[fa[x]]; 30 val[x] %= 2; 31 return fa[x] = tmp; 32 } 33 34 int main(){ 35 while(scanf("%d %d %d", &n, &p1, &p2) && !(n == 0 && p1 == 0 && p2 == 0)){ 36 init(); 37 for(int i = 1; i <= n; i++){ 38 char str[5]; 39 int a, b; 40 scanf("%d %d %s", &a, &b, str); 41 int tmp = str[0] == ‘y‘? 0: 1; 42 int rb = find(b), ra = find(a); 43 if(ra != rb){ 44 fa[ra] = rb; 45 val[ra] = (val[b] - val[a] + tmp + 2) % 2; 46 } 47 } 48 if(p1 == p2){ 49 puts("no"); 50 continue; 51 } 52 for(int i = 1; i <= xn; i++){ 53 int ri = find(i); 54 if(fb[ri] == 0) fb[ri] = ++bgcnt; 55 bagele[fb[ri]][val[i]].push_back(i); 56 bagcnt[fb[ri]][val[i]]++; 57 } 58 59 // test 60 // puts("ancestors:"); 61 // for(int i = 1; i <= xn; i++) printf("%d:%d\n", i, fa[i]); 62 // for(int i = 1; i <= bgcnt; i++){ 63 // printf("bag %d:\ncnt0:%d cnt1:%d\n", i, bagcnt[i][0], bagcnt[i][1]); 64 // for(int j = 0; j < bagele[i][0].size(); j++) printf("%d ", bagele[i][0][j]); 65 // puts(""); 66 // for(int j = 0; j < bagele[i][1].size(); j++) printf("%d ", bagele[i][1][j]); 67 // puts(""); 68 // } 69 70 dp[0][0] = 1; 71 for(int i = 1; i <= bgcnt; i++){ 72 for(int j = 0; j <= p1; j++){ 73 if(j >= bagcnt[i][0] && dp[i - 1][j - bagcnt[i][0]]){ 74 dp[i][j] += dp[i - 1][j - bagcnt[i][0]]; 75 pre[i][j] = j - bagcnt[i][0]; 76 } 77 if(j >= bagcnt[i][1] && dp[i - 1][j - bagcnt[i][1]]){ 78 dp[i][j] += dp[i - 1][j - bagcnt[i][1]]; 79 pre[i][j] = j - bagcnt[i][1]; 80 } 81 } 82 } 83 // test 84 // printf("dp: %d\n", dp[bgcnt][p1]); 85 // int j = p1, tmp = p1; 86 // for(int i = bgcnt; i > 0; i--){ 87 // printf("pre %d %d: %d\n", i, j,tmp - pre[i][j]); 88 // tmp = pre[i][j]; 89 // j = pre[i][j]; 90 // } 91 if(dp[bgcnt][p1] != 1){ 92 puts("no"); 93 continue; 94 } 95 96 anss.clear(); 97 int tmp = p1, j = p1; 98 for(int i = bgcnt; i > 0; i--){ 99 int tmx = tmp - pre[i][j]; 100 if(bagcnt[i][0] == tmx){ 101 for(int k = 0; k < bagele[i][0].size(); k++) 102 anss.push_back(bagele[i][0][k]); 103 } 104 else{ 105 for(int k = 0; k < bagele[i][1].size(); k++) 106 anss.push_back(bagele[i][1][k]); 107 } 108 tmp = pre[i][j]; 109 j = pre[i][j]; 110 } 111 sort(anss.begin(), anss.end()); 112 for(int i = 0; i < anss.size(); i++){ 113 printf("%d\n", anss[i]); 114 } 115 puts("end"); 116 } 117 }
题目:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 3677 | Accepted: 1186 |
Description
Input
Output
Sample Input
2 1 1 1 2 no 2 1 no 3 2 1 1 1 yes 2 2 yes 3 3 yes 2 2 1 1 2 yes 2 3 no 5 4 3 1 2 yes 1 3 no 4 5 yes 5 6 yes 6 7 no 0 0 0
Sample Output
no no 1 2 end 3 4 5 6 end
Source
标签:测试数据 print future 一个 scan always down 统计 ict
原文地址:http://www.cnblogs.com/bolderic/p/7298280.html