题目链接:Galaxy at War
题意:在一个给定的
n∗m
的棋盘内的若干个位置
(xi,yi)
有
wi
个水晶,同时有t个冥想球和
s
个污染源,每一次可以选定一个位置
题解:这个游戏是一个简单的阶梯博弈,因为在
(n,m)
处有污染源且所有冥想球与污染源的距离为奇数,那么我们只需要考虑与冥想球曼哈顿距离为偶数的的点即可。我们把这些点的水晶个数异或起来,如果是0,代表先手按照Nim博弈的取法取就行,因为后手不论怎么采取策略,先手一定有办法移动水晶使得局面必败(证明)。所以我们对于每一堆水晶,判断其是否和某一个它能够移动到的冥想球的曼哈顿距离为偶数,然后把这些堆的数目异或得到答案。由于从题意可以推出每一对冥想球之间的距离一定是偶数,所以我们直接判断是否和
(n−1,m)
处的冥想球距离为偶数即可,对于
x=n
的水晶记录
x=n
的冥想球
y
<script type="math/tex" id="MathJax-Element-553">y</script>坐标最大值特判即可。
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 500005;
pair<int,int> med[N],pol[N];
struct Ct{
int x,y,w;
Ct(){}
Ct(int x,int y,int w):x(x),y(y),w(w){}
};
vector<Ct>c;
int main(){
int T,n,m,k,x,y,w,t,s,mx;
scanf("%d",&T);
while(T--){
mx=0;
scanf("%d %d %d",&n,&m,&k);
c.clear();
for(int i=1;i<=k;i++){
scanf("%d %d %d",&x,&y,&w);
c.push_back(Ct(x,y,w));
}
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%d %d",&med[i].first,&med[i].second);
if(med[i].first==n)
mx=max(mx,med[i].second);
}
scanf("%d",&s);
for(int i=1;i<=s;i++)
scanf("%d %d",&pol[i].first,&pol[i].second);
int ans=0;
for(int i=0;i<k;i++){
if(c[i].x<n&&(abs(c[i].x-n+1)+abs(c[i].y-m))%2==0)
ans^=c[i].w;
else if(c[i].x==n&&c[i].y<=mx&&abs(c[i].y-mx)%2==0)
ans^=c[i].w;
}
puts(ans?"win":"lose");
}
return 0;
}