题目描述
野猫与胖子,合起来简称肥猫,是一个班的同学,他们也都是数学高手,所以经常在一起讨论数学问题也就不足为奇了。
一次,野猫遇到了一道有趣的几何游戏题目,便拿给胖子看。游戏要求在一个有 n 个顶点凸多边形上进行,这个凸多边形的 n-3n−3 条对角线将多边形分成 n-2个三角形,这 n-3 条对角线在多边形的顶点相交。三角形中的一个被染成黑色,其余是白色。
双方轮流进行游戏,当轮到一方时,他必须沿着画好的对角线,从多边形上切下一个三角形。切下黑色三角形的一方获胜。胖子一看觉得确实很有趣,不如就一起玩玩吧。假设游戏由野猫先开始,那么野猫是否有必胜的策略呢?请写一个程序帮助野猫算一算。
输入格式
第一行为一个整数 nn,表示多边形的顶点数,多边形的顶点由 0 至 n-1 顺时针标号。
接着的 n-2 行描述组成多边形的三角形。第 i+1 行(1≤i≤n−2) 有三个空格分隔的非负整数 a、b、c ,它们是第 ii 个三角形的顶点编号。第一个给出的三角形是黑色的。
输出格式
只有一行,倘若野猫有必胜策略,输出 JMcat Win
;否则,输出 PZ Win
(注意大小写和空格)。
输入输出样例
输入
6
0 1 2
2 4 3
4 2 0
0 5 4
输出
JMcat Win
说明/提示
4≤n≤5×104。
如果连接一个多边形中任意两点的线段都完全包含于这个多边形,则称这个多边形为凸多边形。
解题思路:
如果博弈论题目没有明显的解题思路,也没有明显的模板可以套用,那么我们就采用自底向上找规律的思路
我们发现最小的是四边形,会分成两个三角形,先手必胜(因为两个三角形都裸露在外面)
如果是五边形,如果黑色三角形裸露在外面,还是先手必胜,如果黑色三角形被包裹在里面,先手切一个就变成了四边形,变成了上面后手必胜的局面
如果是六边形,还是如果黑色裸露在外面,先手必胜,如果不是,先手一定不希望第一刀就把黑色漏在外面,他一定会选择让这个图形变成黑色三角形包裹在里面的五边形,这时候根据前者可知先手必胜
……
通过总结以上我们就可以很清晰的发现解题的规律了,如果这个黑色三角形裸露在外面,则先手必胜,否则判断n的奇偶性,如果是偶数先手必胜,反之后手必胜
另外一开始找出这个规律我就一直在想怎么处理裸露在外面的三角形,想了很久也没有好的方法,觉得自己写的太笨了,就想着去看看题解,看看别人怎么写的,结果发现这个题目是有点问题的,洛谷的数据只要单纯判断奇偶就可以ac,然后我能找到的所有判断裸露三角形的都有bug,假如说五边形,如果说他给的黑色三角形的三点是0 1 4,这个也是裸露在外面的,一个在0的左边,一个在0的右边
下面附上ac代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <queue>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll M=1e7;
const int mod=1e9+7;
ll a[4];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
ll n;
cin>>n;
ll x,y,z;
for(ll i=1;i<=n-2;i++)
{
cin>>x>>y>>z;
if(i==1)
a[1]=x,a[2]=y,a[3]=z;
}
sort(a+1,a+1+3);
if((a[1]==0&&a[2]==n-2&&a[3]==n-1)||(a[1]+1==a[2]&&a[2]+1==a[3])||(a[1]==0&&a[2]==1&&a[3]==n-1))
puts("JMcat Win");
else if((n-2)%2==1)
puts("PZ Win");
else
puts("JMcat Win");
return 0;
}