HDU 6139 Galaxy at War(2017 Multi-University Training Contest 8)

来源:互联网 发布:淘宝销售数据统计 编辑:程序博客网 时间:2024/06/06 20:37

题目链接:Galaxy at War
题意:在一个给定的nm的棋盘内的若干个位置(xi,yi)wi个水晶,同时有t个冥想球和s个污染源,每一次可以选定一个位置(u,v),将t个水晶移动到(u+1,v)或者(u,v+1),如果这个位置有冥想球,那么可以在(u+1,v)(u,v+1)处制造t个水晶。如果这个位置有污染源,那么只有t2个水晶能保存下来。(n,m)处有一个污染源,(n1,m)处有一个冥想球。并且每一个冥想球和每一个污染源之间的距离是奇数。问维德和尤达大师轮流行动,不能行动的那一方输掉游戏,问维德是否能取得胜利。
题解:这个游戏是一个简单的阶梯博弈,因为在(n,m)处有污染源且所有冥想球与污染源的距离为奇数,那么我们只需要考虑与冥想球曼哈顿距离为偶数的的点即可。我们把这些点的水晶个数异或起来,如果是0,代表先手按照Nim博弈的取法取就行,因为后手不论怎么采取策略,先手一定有办法移动水晶使得局面必败(证明)。所以我们对于每一堆水晶,判断其是否和某一个它能够移动到的冥想球的曼哈顿距离为偶数,然后把这些堆的数目异或得到答案。由于从题意可以推出每一对冥想球之间的距离一定是偶数,所以我们直接判断是否和(n1,m)处的冥想球距离为偶数即可,对于x=n的水晶记录x=n的冥想球y坐标最大值特判即可。

#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;}
原创粉丝点击