zoukankan      html  css  js  c++  java
  • BZOJ 2927: [Poi1999]多边形之战 (博弈)

    题意

    有一个凸多边形,顶点编号逆时针从0到n-1.现在这个n边形被剖分成n-2个三角形,给出这n-2个三角形的顶点,保证这是用n-3条不交叉的对角线划分出来的.现在第一个三角形是黑色,其他都是白色.两名玩家轮流操作,每一次能够把处于外层的三角形取走,最后取到黑色三角形的人获胜,问先手是否必胜.这里外层的定义是有两条边暴露在外面.

    分析

    我们把每一个三角形看成一个点,相邻的三角形连边(类似于对偶图),那么就会形成一棵树,且每个点的度数最大为3.我们将黑色三角形设为根,形成一棵有根树.那么一个点能取当且仅当它的度数为1.那么对于白色三角形(非根节点),必须是这个点成为叶节点才能取走.对于黑色三角形(根节点),必须只剩下一个子树跟它相连才能取走.那么必胜状态就是根节点只连接了一棵子树.而必败状态是根节点分别连接两个叶节点.因为如果这两个不是叶节点,那么当前的人一定会取下面的点来拖延时间(可以这么理解).所以除去根节点和这两个叶节点,剩下的n-3个节点如果是奇数,就表示先手取走了下面的最后一个点,把必败状态留给后手,所以先手必胜.反之先手必败.也就是说n为偶数先手必胜,n为奇数先手必败.

    特殊情况是本来根节点就能被取走,特判一下就行了.

    这道题满足了编号逆时针有序,那么其实白色三角形的分布与答案无关,我们只需要看黑色三角形连了几条边就行了.如果黑色三角形的某两个顶点编号不连续,那么这条边的另一头就会有一个三角形,所以边数+1.三条边都判一下就知道根节点的度数了.

    CODE

    #include <cstdio>
    int x, y, z, n, deg;
    inline bool chk(int i, int j) { return (i+1)%n!=j && (j+1)%n!=i; }
    int main () {
    	scanf("%d%d%d%d", &n, &x, &y, &z);
    	deg = chk(x, y) + chk(y, z) + chk(z, x);
    	if(deg == 1 || !(n&1)) puts("TAK");
    	else if(n&1) puts("NIE");
    }
    
  • 相关阅读:
    linux g++编译dxf文件C++解析库dxflib
    linux g++使用总结
    一个使用three.js的网页DXF文件查看器dxf viewer
    node.js教程基础:node.js访问操作系统
    node.js教程基础:node.js全局对象
    node.js教程基础:node.js命令行选项
    node.js教程基础:node.js包管理器
    node.js教程基础:node.js REPL
    node.js教程基础:第一个node.js程序
    node.js教程基础:node.js安装
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039388.html
Copyright © 2011-2022 走看看