zoukankan      html  css  js  c++  java
  • 蓝桥杯T37(nim博弈)

    题目链接:http://lx.lanqiao.cn/problem.page?gpid=T37

    题意:中文题诶~

    思路:nim博弈

    个人感觉这题最难的地方是将题目转换为博弈模型,如果能将之转换为博弈模型的话题目也就迎刃而解啦;

    本题的解法是将相邻的两个和尚之间的台阶数目看做一堆石头,那么就变成nim博弈啦,对于和尚数目为奇数的情况,直接将最后一个和尚忽略或者在最后那个和尚后面再加一个和尚即可,后者相当于加了一堆数目为0的石头,和前者没什么区别;

    本题和一般nim博弈的不同之处是本题中石头的数目是可以增加的,其实就是将后面那个和尚往后移啦;如果直接按照博弈思路去求那个bi'的话得到的解可能不是最小的(在本题中最后一组数据会wa)。要得到最小解的话就需要我们枚举每一个和尚并分别判断石头增加和减少的情况啦。。

    直接求bi'的代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #define MAXN 110
     4 using namespace std;
     5 
     6 int a[MAXN], b[MAXN];
     7 
     8 int main(void){
     9     char ch;
    10     int pos=0;
    11     while(1){
    12         scanf("%d%c", &a[pos++], &ch);
    13         if(ch=='
    '){
    14             break;
    15         }
    16     }
    17     if(pos&1){
    18         pos--;
    19     }
    20     for(int i=0; i<pos; i+=2){
    21         b[i>>1]=a[i+1]-a[i]-1;
    22     }
    23     pos>>=1;
    24     int ans=0;
    25     for(int i=0; i<pos; i++){
    26         ans^=b[i];
    27     }
    28     if(!ans){//面对奇异局势,必败
    29         cout << -1 << endl;
    30     }else{
    31         for(int i=0; i<pos; i++){
    32             if((ans^b[i])<b[i]){//找到bi'替换bi使变成奇异局势
    33                 int cnt=ans^b[i];
    34                 cout << a[i<<1] << " " << a[i<<1]+(b[i]-cnt) << endl;
    35                 break;
    36             }
    37         }
    38     }
    39     return 0;
    40 }
    41 
    42 // 1 4 8 12 16 19 28 33 35 36 40 45 52 66 67 68 69 77 85 99 102 134 155 211 214 216 355 376 400 412
    43 // 134 148
    View Code

    枚举求解的代码:

    #include <iostream>
    #include <stdio.h>
    #define MAXN 110
    using namespace std;
    
    int a[MAXN], b[MAXN];
    
    int main(void){
        char ch;
        int pos=0;
        while(1){
            scanf("%d%c", &a[pos++], &ch);
            if(ch=='
    '){
                break;
            }
        }
        if(pos&1){
            pos--;
        }
        int len=pos;
        for(int i=0; i<pos; i+=2){
            b[i>>1]=a[i+1]-a[i]-1;
        }
        pos>>=1;
        int ans=0;
        for(int i=0; i<pos; i++){//面对奇异局势,必败
            ans^=b[i];
        }
        if(!ans){
            cout << -1 << endl;
        }else{
            for(int i=0; i<len; i++){//枚举每一个人移动的情况
                for(int j=a[i]+1; j<a[i+1]; j++){//当前和尚可以向前移动到前一个和尚下面一个台阶
                    if(i&1){//若当前是第偶数个和尚,则相当于当前堆石头数目增加
                        int cnt=j-a[i-1]-1;
                        if(!(ans^cnt^b[i/2])){//移动后变成奇异局势
                            cout << a[i] << " " << j << endl;
                            return 0;
                        }
                    }else{//当前是第奇数个和尚,则相当于当前堆石头数目减少
                        int cnt=a[i+1]-j-1;
                        if(!(ans^cnt^b[i/2])){//移动后变成奇异局势
                            cout << a[i] << " " << j << endl;
                            return 0;
                        }
                    }
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java 基础笔记
    专业人士给我的JAVA学习建议
    JAVA版2048
    学习构建之法后的疑问
    角色职责及技术需求相关思考
    使用Composer安装Yii2框架+Windows下的XAMPP部署Yii2
    MiniProgram开发--云开发(1)
    Android Studio丢失Logcat问题
    SSH异常处理记录
    Android环境搭建与通过命令行方式创建Android应用
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6576384.html
Copyright © 2011-2022 走看看