我又写了一个简洁版的2.0; 可以作为博弈搜索树的模板  ;

https://www.cnblogs.com/xidian-mao/p/9389974.html

废话ps: 开始觉得这是一道简单得博弈 3*3暴力肯定可以解决问题   刚该开始得思路是直接dfs()判断谁输谁赢了,后来发现题意要输出最优解得情况(最后卡在哪好久:

还是自己太自信了: 最后五点去上了个厕所;路上想到了dfs可以返回赢的最小步数和输的最大步数这应该是最优解了-----T&T 最后没时间交了,回来补得,试了一些数据感觉没有问题,如果有bug欢迎指出,还是自己太菜了)

题目分析:

博弈——每个人采取最优策略,问最后有几个空格;

首先写一个check()判断现在得局面 谁赢谁输 平局 还是继续可以下  这个暴力枚举即可

 int check () {
for (int i=;i<=;i++) {
int x=mp[i][];
if (x==) continue;
for (int j=;j<=;j++) {
if (mp[i][j]!=x)
break;
if (j==)
return x;
}
}
for (int i=;i<=;i++) {
int x=mp[][i];
if (x==) continue;
for (int j=;j<=;j++) {
if (mp[j][i]!=x)
break;
if (j==)
return x;
}
}
int x=mp[][];
if (x&&mp[][]==mp[][]&&mp[][]==mp[][]) return x;
x=mp[][];
if (x&&mp[][]==mp[][]&&mp[][]==mp[][]) return x;
    if (num==0)  return 0;
return -;
}

check()返回值:

0:平局

1:1赢

2: 2赢

-1:局面可以继续下

核心int  dfs(x,y,p) // 作用: 当p选手在x,y位置放下棋子时如果必赢,最少赢多少步,如果必输,最多可以输多少步;

思路转变当你放下一个棋子还不能赢得比赛胜利时,比赛得主动权已经移交给对方了

此时对方dfs()遍历搜索最优路径,只有当对方必败时,你才会赢, 只要对方有一种情况可以赢,你就要gg了

对方如果一定会赢 会选择最小赢得步数  这个路径也是你输得步数+1

如果对方一定会输 她会选择一个输得最大步数  这个步数等于你赢得步数+1;

关键点:你下完之后主动权已经在于对方 对方得最优策略才是你下完这一步得最终结果

dfs():返回值

x>0 :必赢下最下步数是x

x==0 :是平局

x<0 :必输下最多得步数

 int dfs (int x,int y,int t)  {
mp[x][y]=t; num--;
int ans=check();
if (ans==t) { mp[x][y]=; num++; return ; } // 下完这一步立即获胜
if (ans==) { mp[x][y]=; num++; return ; } // 下完这一步平局 // 不存在你下完就立即输。。。。。
int k=;
if (t==) k=;// k 交换主动权 你下完之后得最终结果取决于对方
int m1=;// 初始化赢得最小步
int m2=;// 输得最大步 (用负数表示)
ans=-;// 假设对方一定输
for (int i=;i<=;i++) {
for (int j=;j<=;j++) {
if (mp[i][j]==) {
int tmp=dfs (i,j,k);
ans=max (ans,tmp);// 只要对方一种情况赢, ans就大于0, t一定会输
if (tmp>) {
m1=min(m1,tmp);// 赢得最小步
}
if (tmp<) {
m2=min(m2,tmp);//输得最大步 (用负数表示)
}
}
}
}
mp[x][y]=; num++;
if (ans==) return ;
if (ans>) return -(m1+);// 如果对方会赢 你就输这个步数取决于对方
return -(m2-);//对方无论怎么走都输

完整代码   (本人qq 821474143  如果想的不周全,欢迎大家指教_


#include <bits/stdc++.h>
using namespace std;
int mp[10][10];
int num1,num2;// num1 1数目  num2 2数目
int num;// 空格数目
int n;
int check () {
    for (int i=1;i<=3;i++) {
        int x=mp[i][1];
        if (x==0) continue;
        for (int j=1;j<=3;j++) {
            if (mp[i][j]!=x)
                break;
            if (j==3)
                return x;
        }
    }
     for (int i=1;i<=3;i++) {
        int x=mp[1][i];
        if (x==0) continue;
        for (int j=1;j<=3;j++) {
            if (mp[j][i]!=x)
                break;
            if (j==3)
                return x;
        }
    }
    int x=mp[1][1];
    if (x&&mp[1][1]==mp[2][2]&&mp[2][2]==mp[3][3]) return x;
    x=mp[2][2];
    if (x&&mp[3][1]==mp[2][2]&&mp[2][2]==mp[1][3])  return x;
    if (num==0)  return 0;
    return -1;
}
int dfs (int x,int y,int t)  {
    mp[x][y]=t;  num--;
    int ans=check();
    if (ans==t)  { mp[x][y]=0; num++; return 1; }
    if (ans==0)  { mp[x][y]=0; num++; return 0; }
    int k=1;
    if (t==1)  k=2;
    int m1=100;
    int m2=0;
    ans=-1;
    for (int i=1;i<=3;i++)       {
        for (int j=1;j<=3;j++) {
            if (mp[i][j]==0) {
                int tmp=dfs (i,j,k);
                ans=max (ans,tmp);
                if (tmp>0)  {
                   m1=min(m1,tmp);
                }
                if (tmp<0) {
                    m2=min(m2,tmp);
                }
            }
        }
    }
    mp[x][y]=0;  num++;
    if (ans==0)   return 0;
    if (ans>0)   return -(m1+1);
    return -(m2-1);


}
int main ()
{
    cin>>n;
    while (n--) {
        num1=0;
        num2=0;
        for (int i=1;i<=3;i++)
            for (int j=1;j<=3;j++) {
                cin>>mp[i][j];
                if (mp[i][j]==1) num1++;
                else if (mp[i][j]==2) num2++;
            }
        num=3*3-num1-num2;
        int ans=check();
        //cout<<ans<<endl;
        if (ans==1)  cout<<num+1<<endl;
        else if (ans==2) cout<<-(num+1)<<endl;
        else if (ans==0) cout<<"0"<<endl;
        else {
            int m1=100;
            int m2=0;
            int x=2;
            if (num1==num2)  x=1;
            int ans=-1;
            for (int i=1;i<=3;i++)       {
                for (int j=1;j<=3;j++) {
                    if (mp[i][j]==0) {
                         int t=dfs (i,j,x);
                          ans=max (ans,t);
                          if (t>0) {
                            m1=min (t,m1);// 赢得最小步数
                          }
                          if (t<0) {
                            m2=min (t,m2);  //输的最大步数
                          }
                    }
                 }
            }
            if (ans>0)       
              if (x==1) cout<<num-m1+1<<endl;
              else      cout<<-(num-m1+1)<<endl;
            else if (ans==0)   cout<<"0"<<endl;
            else   
              if (x==2)  cout<<num+m2+1<<endl;
              else       cout<<-(num+m2+1)<<endl;
        }
    }
    return 0;
}


一个典型得数据

1 0 0

0 0 0

0 0 2

电脑给出的是1赢 你能一次走对使1赢吗?真是有趣

博弈___ xdoj+1045

定义一种新的黑白棋:

1. 棋盘大小为5*5的格子;

2. 有些格子不能放棋子;

3. 同一个格子最多放一个棋子;

4. 先手执白棋,后手执黑棋;

5. 先手第一次可以把棋放在任意可以放的位置上;

6. 接下来两人轮流放棋子,这个棋子必须与上一个人放的棋子相邻

请问:两人都是最优策略,是先手赢,还是先手输?

输入

有多组输入数据,第一行为一个数字T,代表有T组输入数据 (0<T≤10)。

接下来为T组数据。

每组数据分5行、每行5个数字构成,每个数字为0或1。0表示这个位置可以放棋子,1表示这个位置不能放棋子。

输出

对于每组数据,在一行上输出“win”或“lose”,表示先手赢或输。

样例输入

2
11111
11111
11111
11111
00000
11111
11111
11111
11111
10000

样例输出

win
lose 暴力枚举!!!
 #include <bits/stdc++.h>
using namespace std;
const int n=;
bool mp[][];// 地图 每一格能否放
bool visit[][];// 遍历访问
int dx[]={,,-,};
int dy[]={,-,,};
bool dfs (int x, int y) {
visit[x][y]=;
int flag=;
for (int i=;i<;i++) {
int tx=x+dx[i];
int ty=y+dy[i];
if (tx>=&&tx<=n&&ty>=&&ty<=n&&!visit[tx][ty]&&!mp[tx][ty]) {
int tmp=dfs (tx,ty);
if (tmp) {
flag=;
break;
}
}
}
visit[x][y]=;
return flag;
}
int main ()
{
int T;
scanf ("%d",&T);
while (T--) {
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
scanf ("%1d",&mp[i][j]);
int flag=;
for (int i=;i<=n&&!flag;i++)// 二重循环的遍历的问题
for (int j=;j<=n;j++) {
memset (visit,,sizeof(visit));
if (!mp[i][j]) {
flag=dfs (i,j);
if (flag) break;
}
}
if (flag) printf ("win\n");
else printf ("lose\n");
}
return ;
}
 

第十三次CCF第四题 1803——04 博弈的更多相关文章

  1. CCF第四题无向图打印路径

    #include<iostream> #include<vector> #include<algorithm> #include<stack> #def ...

  2. CCF第四题无向图打印路径 欧拉问题

    #include<iostream> #include<vector> #include<algorithm> #include<stack> #def ...

  3. 网络流二十四题,题解summary

    没有全部写完,有几题以后再补吧. 第一题:最简单的:飞行员配对方案问题 讲讲这个题目为什么可以用网络流? 因为这个题目是要进行两两之间的匹配,这个就可以想到用二分图匹配,二分图匹配又可以用网络流写. ...

  4. Java-集合(没做出来)第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列。 例如: List list = new ArrayList(); list.add(“Hello”); list.add(“World”); list.add(“Learn”); //此时list 为Hello World Learn reverseL

    没做出来 第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列. 例如: List list = new ArrayList(); list.a ...

  5. 经典算法题每日演练——第十四题 Prim算法

    原文:经典算法题每日演练--第十四题 Prim算法 图论在数据结构中是非常有趣而复杂的,作为web码农的我,在实际开发中一直没有找到它的使用场景,不像树那样的频繁使用,不过还是准备 仔细的把图论全部过 ...

  6. NOIP2010-普及组复赛-第四题-三国游戏

    题目描述 Description 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏.  在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有 N 位武将(N为偶数且不 ...

  7. CTF---Web入门第十四题 忘记密码了

    忘记密码了分值:20 来源: Justatest 难度:中 参与人数:7706人 Get Flag:2232人 答题人数:2386人 解题通过率:94% 找回密码 格式:SimCTF{ } 解题链接: ...

  8. hiho_offer收割18_题解报告_差第四题

    I.求逆元欧几里得方法 II.模拟细心+耐心 *本人感悟:自己的错误在于:对于这道模拟题没有耐心静下来一字一字看题,一行一行调错,一步一步调试,我要引以为戒. III.dpf[i][j][k]=max ...

  9. 第六届蓝桥杯java b组第四题

    第四题 两个整数做除法,有时会产生循环小数,其循环部分称为:循环节. 比如,11/13=6=>0.846153846153….. 其循环节为[846153] 共有6位. 下面的方法,可以求出循环 ...

随机推荐

  1. springmvc 自定义view支持json和jsonp格式数据返回

    1.如果controlloer上用@ResponseBody注解,则用<mvc:message-converter>里面配置的json解析器进行解析 <mvc:annotation- ...

  2. ubuntu启用root登陆

    ubuntu系统不能够默认以root用户登陆系统如果你为了方便开发想每次登陆的时候以root用户登陆那么需要手动的做写更改打开终端 首先输入命令 sudo passwd  root更新你的密码然后输入 ...

  3. 【Query】使用java对mysql数据库进行查询操作

    操作步骤: 1.加载数据库驱动(先在工程里加载数据库对应的驱动包) 2.获取连接 3.根据连接建立一个可执行sql的对象 4.执行sql语句 5.关闭连接 代码: package database; ...

  4. 微信小程序web-view使用测试总结

    1.后台配置业务域名. 2.在开发者工具的web-view组件中绑定业务域名. 3.点击开发者工具的详情按钮,选择调试基础库高版本,如果不设置,有可能绑定的业务域名内容不显示. 4.如果是公众号上的内 ...

  5. 4.2计算字符的ASCII碼

    Q:终端输入一个字符,输出ASCII碼 #include<stdio.h> int main() { char c; printf("input a charscter:&quo ...

  6. UVa LA 3213 - Ancient Cipher 水题 难度: 0

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  7. eclipse package视图和navigator视图的区别

    package视图是适合开发的视图,因为开发时我们只关注源文件,并不关注编译后的二进制文,所有在该视图中存放二进制文件的classes文件被隐藏了,而navigator视图,就是项目在工作空间中存放的 ...

  8. S2 深入.NET和C#编程 笔试测试错题积累

    ---恢复内容开始--- <深入.NET平台和C#编程>内部测试题-笔试试卷错题积累 1: 1) 以下关于序列化和反序列化的描述错误的是( C). a) 序列化是将对象的状态存储到特定存储 ...

  9. (C/C++学习笔记) 二. 数据类型

    二. 数据类型 ● 数据类型和sizeof关键字(也是一个操作符) ※ 在现代半导体存储器中, 例如在随机存取存储器或闪存中, 位(bit)的两个值可以由存储电容器的两个层级的电荷表示(In mode ...

  10. ios 第4天

    dealloc method  会在对象释放前调用这个方法(函数)  可以让对象在释放前把一些自己申请的对象 先释放了    满足 谁申请  谁释放 的原则 例如    dealloc 会自动调用   ...