HDU 6139 Galaxy at War 2017 MUTC

这题在多校现场,才22队出。虽然最后结果是25个队,但是有三个队是随机数过的,是的,全凭运气。


为什么我知道呢,因为第一个用随机数A掉的就是我……


官方题解:

这是本场比赛最大的坑题.
首先, 棋盘就是一个二分图, 可以得出任意一个Meditation (u, v)(u,v)和任意一个pollutant (a, b)(a,b)u+vu+vu-vuv就是把曼哈顿距离写成了切比雪夫距离而已...
剩下的部分就是一个简单的阶梯博弈. 把所有和Meditation的曼哈顿距离为偶数的点的水晶数异或起来, 如果为0则lose, 否则win.
这里的阶梯博弈证明就是, 对于先手, 如果上面方法算出来的sg值大于0, 那么按照nim取石子游戏的步骤一样, 把某个奇点(和Meditation曼哈顿距离为偶数的点)移到偶点. 如果对面选择把偶点移到奇点, 由于奇点是不存在pollutant的, 所以水晶数不会减少, 那么这时候先手只需要把同样数量的水晶从奇点移到偶点即可.
如果得到的值是0, 那么就变成一个对方先手且sg不为0的情况, 所以此时先手必败.
正确的AC方式(来自 http://blog.csdn.net/cantsayaword/article/details/77370443):

#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;
}


我的随机输出写法(别试了,想通过,很难的):

#include<map>
#include<set>
#include<list>
#include<stack>
#include<deque>
#include<queue>
#include<vector>
#include<sstream>
#include<iomanip>
#include<iostream>
#include<math.h>
#include<ctype.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<functional>
#define CPY(A,B)memcpy(A,B,sizeof(A))
#define fin freopen("in.txt","r",stdin)
#define fout freopen("out.txt","w",stdout)
typedef long long LL;
typedef unsigned long long uLL;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
const LL INFF=0x3f3f3f3f3f3f3f3fLL;
const double OO=1e20;
const double EPS=1e-9;
const double PI=acos (-1.0);
int dx[]= {0,1,0,-1};
int dy[]= {1,0,-1,0};
using namespace std;
int gcd (const LL &a,const LL &b) {
    return b==0?a:gcd (b,a%b);
}
inline int dcmp (double a,double b) {
    if (fabs (a-b) <EPS) { return 0; }
    return a<b?-1:1;
}
const int M=30030;
int main() {
    int T;cin>>T;
    srand((unsigned)time(NULL));
    while(T--){
        (rand()%2==0)?puts("lose"):puts("win");
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值