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. 高效实时的网络会议数据传输库—UDT

    在视频会议系统的研发当中,我们的音.视频数据必须要有相应的可靠性作为保障,因为视频会议系统是一个实时性非常强的系统,如果其数据在网络不太好的情况下,有可能会出现丢包.数据延迟.数据堵塞等现象,出现这些 ...

  2. pthread_create & pthread_exit

    http://www.cppblog.com/saha/articles/189802.html 1.   pthread_create    #include <pthread.h>   ...

  3. 【[SDOI2009]晨跑】

    板子 题意就是每个点只能经过一次 所以非常显然拆点,除去\(1,n\)每个点\(i\)向\(i'\)连一条容量为\(1\)费用为\(0\)的边 剩下的边按照输入给出的建就好了 代码 #include& ...

  4. 2018.11.1 Hibernate中的Mapper关系映射文件

    Customer.hbm.xml 基本的参数都在里面了 <?xml version="1.0" encoding="UTF-8"?> <!DO ...

  5. vue常用事件

    一.事件监听 1. banner_edit.$watch('bannerForm.type', function () { //执行其他代码 console.log(666); this.banner ...

  6. javap(反汇编命令)

    用法: javap <options> <classes> 其中, 可能的选项包括: -help  --help  -?        输出此用法消息 -version     ...

  7. No space left on device错误解决

    No space left on device错误解决笔记 今天准备重启下数据库(linux oracle11g) conn /as sysdba; 出现这样的错误No space left on d ...

  8. 【洛谷P3818】小A和uim之大逃离 II

    小A和uim之大逃离 II 题目链接 比较裸的搜索,vis[i][j]再加一层[0/1]表示是否使用过魔液 转移时也将是否使用过魔液记录下来,广搜即可 #include<iostream> ...

  9. java递归菜单树转换成pojo对象

    package com.cjonline.foundation.authority.pojo; import java.util.ArrayList; import java.util.Collect ...

  10. 使用百度新闻RSS

    function getbaidu() { $result=""; //RSS源地址列表数组 $rssfeed = array("http://news.baidu.co ...