Find the Winning Move

链接

题意:

4*4的棋盘,给出一个初始局面,问先手有没有必胜策略?

  有的话输出第一步下在哪里,如果有多个,按(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1) ... 的顺序输出第一个。没有输出“#####”。

分析:

  极大极小搜索 或者 对抗搜索,α+β剪枝。

  极大极小搜索:每个人都会进行最聪明的决策,假设有1号玩家为我们希望的玩家(即判断他能否有必胜的走法),那么对于一号玩家进行决策时,让他去所有后继状态中最大的,即Max节点。而二号玩家也会进行最聪明的决策,他会去所有后继状态中最小的,即Min节点。于是我们搜索出所有的后继状态的估价值, 判断。

  α+β剪枝:思想:搜索到一个节点时,如果他进行最优决策,已经比父节点档当前的答案不优了,这个节点父节点是不会选的,这个节点的其他子节点的也不用搜了。

代码:

α+β剪枝:16ms

 #include<cstdio>

 char g[][];
int ansx,ansy; int judge() {
int za = ,zb = ; // 主对角线
int fa = ,fb = ; // 副对角线
for (int i=; i<=; ++i) {
if (g[i][i] == 'x') za++;
else if (g[i][i]=='o') zb++;
if (g[i][-i] == 'x') fa++;
else if (g[i][-i]=='o') fb++;
}
if (za== || fa==) return ;
if (zb== || fb==) return -; for (int i=; i<=; ++i) {
int ra = ,rb = ; // 行
int ca = ,cb = ; // 列
for (int j=; j<=; ++j) {
if (g[i][j] == 'x') ra++;
else if (g[i][j] == 'o') rb++;
if (g[j][i] == 'x') ca++;
else if (g[j][i] == 'o') cb++;
}
if (ra == || ca == ) return ;
if (rb == || cb == ) return -;
} return ;
}
int Minimax(int player,int alpha,int beta) {
int res= judge();
if (res) return res;
if (player) {
for (int i=; i<=; ++i)
for (int j=; j<=; ++j)
if (g[i][j] == '.') {
g[i][j] = 'x';
res = Minimax(player^,alpha,beta);
g[i][j] = '.';
if (res > alpha) alpha = res,ansx = i,ansy = j;
if (alpha >= beta) return alpha;
}
return alpha; //-
}
else {
for (int i=; i<=; ++i)
for (int j=; j<=; ++j)
if (g[i][j] == '.') {
g[i][j] = 'o';
res = Minimax(player^,alpha,beta);
g[i][j] = '.';
if (res < beta) beta = res;
if (alpha >= beta) return beta;
}
return beta; //-
}
} int main() {
char op[];
while (scanf("%s",op) && op[]!='$') {
int cnt = ;
for (int i=; i<=; ++i) {
scanf("%s",g[i]+);
for (int j=; j<=; ++j)
if (g[i][j] != '.') cnt++;
}
if (cnt <= ) {
puts("#####");continue;
}
int ans = Minimax(,-,);
if (ans > ) printf("(%d,%d)\n",ansx-,ansy-);
else puts("#####");
}
return ;
}

没有α+β剪枝:63ms

 #include<cstdio>
#include<cstdlib>
#include<algorithm> char g[][];
int ansx,ansy,f; int judge() {
int za = ,zb = ; // 主对角线
int fa = ,fb = ; // 副对角线
for (int i=; i<=; ++i) {
if (g[i][i] == 'x') za++;
else if (g[i][i]=='o') zb++;
if (g[i][-i] == 'x') fa++;
else if (g[i][-i]=='o') fb++;
}
if (za== || fa==) return ;
if (zb== || fb==) return -; for (int i=; i<=; ++i) {
int ra = ,rb = ; // 行
int ca = ,cb = ; // 列
for (int j=; j<=; ++j) {
if (g[i][j] == 'x') ra++;
else if (g[i][j] == 'o') rb++;
if (g[j][i] == 'x') ca++;
else if (g[j][i] == 'o') cb++;
}
if (ra == || ca == ) return ;
if (rb == || cb == ) return -;
} return ;
}
int Minimax(int player,bool flag) {
int res= judge(),t;
if (res) return res;
if (player) {
for (int i=; i<=; ++i)
for (int j=; j<=; ++j)
if (g[i][j] == '.') {
g[i][j] = 'x';
t = Minimax(player^,);
if (t > res) {
res = t;
if (flag) {
printf("(%d,%d)\n",i-,j-);
f = ;
return ;
}
}
g[i][j] = '.';
}
return res;
}
else {
res = ;
for (int i=; i<=; ++i)
for (int j=; j<=; ++j)
if (g[i][j] == '.') {
g[i][j] = 'o';
res = std::min(res,Minimax(player^,));
g[i][j] = '.';
}
return res; //-
}
} int main() {
char op[];
while (scanf("%s",op) && op[]!='$') {
int cnt = ;
f = ;
for (int i=; i<=; ++i) {
scanf("%s",g[i]+);
for (int j=; j<=; ++j)
if (g[i][j] != '.') cnt++;
}
if (cnt <= ) {
puts("#####");continue;
}
Minimax(,);
if (!f) puts("#####");
}
return ;
}

POJ 1568 Find the Winning Move的更多相关文章

  1. POJ 1568 Find the Winning Move(极大极小搜索)

    题目链接:http://poj.org/problem?id=1568 题意:给出一个4*4的棋盘,x和o两人轮流放.先放够连续四个的赢.给定一个局面,下一个轮到x放.问x是否有必胜策略?若有,输出能 ...

  2. poj 1568 Find the Winning Move 极大极小搜索

    思路:用极大极小搜索解决这样的问题很方便!! 代码如下: #include <cstdio> #include <algorithm> #define inf 10000000 ...

  3. 【迭代博弈+搜索+剪枝】poj-1568--Find the Winning Move

    poj  1568:Find the Winning Move   [迭代博弈+搜索+剪枝] 题面省略... Input The input contains one or more test cas ...

  4. poj1568 Find the Winning Move[极大极小搜索+alpha-beta剪枝]

    Find the Winning Move Time Limit: 3000MS   Memory Limit: 32768K Total Submissions: 1286   Accepted:  ...

  5. 【poj1568】 Find the Winning Move

    http://poj.org/problem?id=1568 (题目链接) 题意 两人下4*4的井字棋,给出一个残局,问是否有先手必胜策略. Solution 极大极小搜索.. 这里有个强力优化,若已 ...

  6. 【POJ1568】【极大极小搜索+alpha-beta剪枝】Find the Winning Move

    Description 4x4 tic-tac-toe is played on a board with four rows (numbered 0 to 3 from top to bottom) ...

  7. POJ 1568 极大极小搜索 + alpha-beta剪枝

    极小极大搜索 的个人理解(alpha-beta剪枝) 主要算法依据就是根据极大极小搜索实现的. 苦逼的是,查了两个晚上的错,原来最终是判断函数写错了..瞬间吐血! ps. 据说加一句 if sum & ...

  8. poj练习题的方法

    poj1010--邮票问题 DFSpoj1011--Sticks dfs + 剪枝poj1020--拼蛋糕poj1054--The Troublesome Frogpoj1062--昂贵的聘礼poj1 ...

  9. poj -2975 Nim

      Nim Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4312   Accepted: 1998 Description ...

随机推荐

  1. Fiori里花瓣的动画效果实现原理

    Fiori里的busy dialog有两种表现形式,一种是下图里的花朵形状,由5个不断旋转的花瓣组成.另一种是下图的3/4个圆环不断旋转的效果. 关于前者的效果,可以看我制作的这个视频.这个视频是手动 ...

  2. react中 props,state与render函数的关系

    我们很明显的能够感受到,react是一门数据驱动的框架,当数据发生变化,页面就会自动发生变化,他背后的原理是怎么样子的呢 比如todolist例子里面,inputValue变了,框里面的内容就会自动变 ...

  3. [18/11/7] Java的基础概念

    java语言的优势是跨平台 ,计算机界的英语,是IT行业的第一大语言 特点是多线程 分布式 健壮性 面向对象 java和JavaScript的关系 雷锋和雷峰塔的关系 或卡巴斯基和巴基斯坦的关系有个基 ...

  4. [转]Android Studio启动时出现unable to access android sdk add-on list

    转载请标明出处:http://blog.csdn.net/xx326664162/article/details/50563122 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的 ...

  5. (转)理解YOLOv2训练过程中输出参数含义

    最近有人问起在YOLOv2训练过程中输出在终端的不同的参数分别代表什么含义,如何去理解这些参数?本篇文章中我将尝试着去回答这个有趣的问题. 刚好现在我正在训练一个YOLOv2模型,拿这个真实的例子来讨 ...

  6. 【luogu P2762 太空飞行计划问题】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2762 算是拍照那个题的加强下. 输入真的很毒瘤.(都这么说但好像我的过了?) #include <qu ...

  7. 【luogu P3369 【模板】普通平衡树(Treap/SBT)】 模板 Scapegoat Tree

    #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> ...

  8. 学习MySql和MongoDB笔记

    首先了解下关系型数据库和非关系型数据库 关系型数据库 SQL关系型数据库采用了关系模式来组织数据,即关系模式为二维表格模型. 主要的数据库:SQL Server,Oracle,Mysql,Postgr ...

  9. Python 学习笔记(六)Python第一个程序

    Python 语句 赋值语句 1.将3对象赋值给了变量a 2.将3,4赋值给了变量a,b >>> a = 3 >>> a ,b = 3,4 >>> ...

  10. poj 2186 Popular Cows :求能被有多少点是能被所有点到达的点 tarjan O(E)

    /** problem: http://poj.org/problem?id=2186 当出度为0的点(可能是缩点后的点)只有一个时就存在被所有牛崇拜的牛 因为如果存在有两个及以上出度为0的点的话,他 ...