多边形游戏(博弈)

问题描述:

多边形游戏是一个双人游戏。游戏在一个有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");
           }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值