标签:
姑且把它归类为一道博弈吧,毕竟这也是在找必胜方案。
十分有意思的一道题目,设计一种方案让你支持的1队获胜。
题目给出了两个很重要的条件:
一共有2n支队伍,每轮比赛会刷掉一半的队伍,紫书上巧妙的做法就是每轮比赛后让题目给的两个性质依然成立,这样1队最终一定能胜出。
方案如下,大致分为3个阶段:
至于为什么这样一定会成功,还请参考紫书。
1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 5 const int maxn = 1030; 6 7 char table[maxn][maxn]; 8 9 int main() 10 { 11 //freopen("in.txt", "r", stdin); 12 13 int n; 14 while(scanf("%d", &n) == 1 && n) 15 { 16 for(int i = 1; i <= n; i++) scanf("%s", table[i] + 1); 17 vector<int> win, lose; 18 for(int i = 2; i <= n; i++) 19 { 20 if(table[1][i] == ‘1‘) win.push_back(i); 21 else lose.push_back(i); 22 } 23 24 int T = n; 25 while(T >>= 1) 26 { 27 vector<int> win2, lose2, final;//进入下一轮1能打败和被打败,以及这一轮混战的队伍 28 bool match; 29 //阶段1:尽可能多的用灰队消灭黑队 30 for(int i = 0; i < lose.size(); i++) 31 { 32 int black = lose[i]; 33 match = false; 34 for(int j = 0; j < win.size(); j++) 35 { 36 int& gray = win[j]; 37 if(gray > 0 && table[gray][black] == ‘1‘) 38 { 39 printf("%d %d\n", black, gray); 40 match = true; 41 win2.push_back(gray);//灰队进入下一轮 42 gray = 0; 43 break; 44 } 45 } 46 if(!match) final.push_back(black);//进入后面的混战 47 } 48 //阶段2:给1队找个对手 49 match = false; 50 for(int i = 0; i < win.size(); i++) 51 { 52 int team = win[i]; 53 if(team > 0) 54 { 55 if(!match) { printf("1 %d\n", team); match = true; } 56 else final.push_back(team);//1已经匹配到对手,该队进入混战 57 } 58 } 59 //阶段3:自由混战,注意到黑队在final中都是挨在一起的 60 for(int i = 0; i < final.size(); i += 2) 61 { 62 printf("%d %d\n", final[i], final[i + 1]); 63 int survive = final[i]; 64 if(table[final[i + 1]][final[i]] == ‘1‘) survive = final[i + 1]; 65 if(table[1][survive] == ‘1‘) win2.push_back(survive); 66 else lose2.push_back(survive); 67 } 68 win = win2; 69 lose = lose2; 70 /*for(int i = 0; i < win.size(); i++) printf("%d ", win[i]); 71 puts(""); 72 for(int i = 0; i < lose.size(); i++) printf("%d ", lose[i]);*/ 73 } 74 } 75 76 return 0; 77 }
标签:
原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4443947.html