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
  • 相关阅读:
    github误fork后删除
    初识javascript
    struts验证框架失效
    Java基础学习1Java标识符及基本类型
    dos 命令行方式下启动和停止MySql服务
    html
    给文本框添加边框的两种方法
    银行家算法
    解决MyEclipse里Tomcat端口被占用而无法启动的情况
    Java近似圆
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6576384.html
Copyright © 2011-2022 走看看