【题目描述】
有n个人围着圆桌坐成一圈,按顺时针顺序依次标为1~n号。对于i(1 < i < n)号来说,其左边为i+1号,右边为i-1号,1号右边为n号,n号左边为1号。
每轮游戏会指定一个坐在圆桌边的人(设为i号),使其向左边的人(设为j号)发起挑战,若挑战成功,则j离开圆桌,若挑战失败,则i离开圆桌,当圆桌边只剩下一个人时,则其为最终胜利者。
现已知,对于任意两个人i号、j号,若i向j发起挑战,结果是成功还是失败。假设每轮游戏可以随意指定发起挑战的人,询问哪些人可以成为最终胜利者。
【输入描述】
第一行输入一个整数n,表示参加游戏的人数;
接下来n行,每行输入n个0或1,若第i行第j列为1,则表示i向j发起挑战会成功,否则表示挑战会失败,第i行第i列的值为0。
【输出描述】
输出一行数,表示可能成为最终胜利者的人的标号,标号按从小到大的顺序输出。
【输入样例】
3
0 1 0
0 0 1
0 1 0
【输出样例】
1 3
【数据范围及提示】
样例解释:
(1)先指定2号向3号发起挑战,3号离开;再指定1号向2号发起挑战,2号离开。此时1号是最终胜利者;
(2)先指定1号向2号发起挑战,2号离开;再指定1号向3号发起挑战,1号离开。此时3号是最终胜利者;
(3)无论如何安排挑战顺序,2号都无法成为最终胜利者。
对于30%的数据,n ≤ 7;
对于100%的数据,n ≤ 100。
源代码: #include<cstdio> int n; bool i[201][201]={0},f[201][201]={0}; int main() //区间型动态规划(环形)。 { scanf("%d",&n); for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) { scanf("%d",&i[a][b]); i[a][b+n]=i[a+n][b]=i[a+n][b+n]=i[a][b]; //i[][]表示挑战结果。 } for (int a=1;a<(n<<1);a++) //f[][]表示两个人有没有可能相邻。 f[a][a+1]=true; for (int a=(n<<1)-2;a>0;a--) //起点。 for (int b=a+2;b<=(n<<1);b++) //终点。 for (int c=a+1;c<b;c++) //中间点。 if (f[a][c]&&f[c][b]&&(i[a][c]||!i[c][b])) //可能相邻且退出条件满足。 { f[a][b]=true; //有可能相邻,中断。 break; } for (int a=1;a<=n;a++) if (f[a][a+n]) //自己与自己有可能相邻,则符合题意。 printf("%d ",a); return 0; } /* 循环类似于环形石子合并。 然后就从小区间枚举起点终点,逐渐扩大,中间点退出有两种情况,前点与其挑战赢,其与后点挑战输。 */