多边形游戏(博弈)

来源:互联网 发布:中建上海设计院 知乎 编辑:程序博客网 时间:2024/05/17 09:05

问题描述:

多边形游戏是一个双人游戏。游戏在一个有n个顶点的凸多边形上进行,这个凸多边形的n-3条对角线将多边形分成n-2个三角形,三角形中的一个被染成黑色,其余是白色。双方轮流进行游戏,当轮到一方时,他必须沿着画好的对角线,从多边形上切下一个三角形。切下黑色三角形的一方获胜。

输入

多组测试数据。每组测试数据第一行n,表示顶点数。多边形的顶点从0到n-1顺时针标号,接着的n-2行描述组成多边形的三角形,且第一行给出的是黑色三角形的描述。当n=0时表示输入结束。

输出

对每组测试数据,输出YES或NO:YES,表示先走的一方有必胜策略;NO,表示先走的一方没有必胜策略。

样例

1

6

0 1 2

2 4 3

4 2 0

0 5 4


YES


思路:本题初看似乎很复杂,设计那么多的边和三角形,但想想,可以将图形进行转换,尝试将多边形的每个三角形看成一个结点,有公共边的三角形所对应的顶点之间连一条边,则所给的图形可以看作是有n-2个结点,n-3条边的一个无向图G。显然,G构成一棵树T,把黑色三角形对应的结点看作树T的根,则树T最多有三棵子树。

接下来考虑必胜策略,显然,若要切掉根结点,则必须先将根的子树切到只剩一根。需要考虑的只是子树的结点个数,用非负整数(x,y,z)表示根的三棵子树的结点个数,不妨设x<=y<=z,则显然z>0。

(1)y=0,则x=0,为必胜状态;

(2)y>0,则最终结局必是(1,0,0),(0,1,0),(0,0,1)的一种;

显然,在(2)情况下,要想让先走的赢,x+y+z为奇数。

算法实现:主要的问题在于x,y,z的求取。由于多边形为顺时针编号,设黑三角形的编号为(i,j,k),假设满足i<j<k,则树T的三棵子树对应的多边形分别有j-i-1,k-j-1,n-(k-i-1)个顶点,也就会包含有j-i-1,k-j-1,n+i-k-1个三角形(结点),排序后,对应x,y,z。


代码:

int main(){          while(cin>>n&&n)          {                     cin>>i>>j>>k;                     n-=3;                     while(n--)                                  cin>>a>>b>>c;                     Swap(i,j,k);//排序:i<j<k                     x=j-i-1,y=k-j-1,z=n+i-k-1;                     Swap(x,y,z);//排序:x<=y<=z                     if(y==0||(x+y+z)&1)                                  printf("Yes\n");                     else                                  printf("No\n");           }}




原创粉丝点击