把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【BZOJ2927】[POI1999] 多边形之战(博弈论SB题)

点此看题面

大致题意:\(n-3\)条对角线将一个\(n\)边形分为\(n-2\)个三角形,其中一个三角形是黑色的。每人每次可以剪开一条对角线,问谁有先剪下黑色三角形的必胜策略。

前言

明明很想认真学学博弈论的说,却不知道为什么会找到这样一道SB题。。。

这种题目只是又来水一发博客而已。。。

分类讨论

实际上,题目中给出\(n-2\)个三角形,除了黑色三角形外其余的都是没用的。

而对于这个黑色三角形,我们只需知道它有几条边不在边界上(即需要剪几次),然后这个三角形也没用了。

接下来,我们就对它需要剪几次来分类讨论:

  • \(1\)次:显然先手必赢。
  • \(2\)次:显然当谁剪了第一次,另一个人可以立刻剪掉第二次,然后就赢了。因此,每个人都会尽量避免去剪第一次。那么他们能干什么呢?只能去剪剩余的\(n-5\)条对角线,直至剪完为止。也就是说,如果\(n-5\)为奇数,先手赢,否则后手赢。
  • \(3\)次:和上一种情况很像,谁剪了第二次,另一个人可以立刻剪掉第三次。而第一次剪不剪其实没什么大影响,因此同样是可以在\(n-5\)条对角线中任意剪,直至剪完。最终的结论也是一样的。

综上所述,先手赢的条件为三角形只需剪\(1\)次,或\(n-5\)为奇数(即\(n\)为偶数)。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 50000
using namespace std;
int n,a,b,c;
int main()
{
	#define S(x,y) (abs((x)-(y))^1&&abs((x)-(y))^(n-1))//判断三角形这条边是否需要剪
	scanf("%d%d%d%d",&n,&a,&b,&c);RI t=S(a,b)+S(a,c)+S(b,c);
	return puts((t==1||(n-5)&1)?"TAK":"NIE"),0;//如果t=1,或n-5为奇数,先手赢
}
posted @ 2020-05-18 09:22  TheLostWeak  阅读(144)  评论(0编辑  收藏  举报