poj1568 极大极小搜索

问题:给出一个4x4 tic-tac-toe 的棋局的局面,问先手 "x" 是不是能找在接下来的一步中

找到一个必胜局面,如果有,输出第一个落子位置(按顺序)。


极大极小搜索策略一般都是使用在一些博弈类的游戏之中: 
这样策略本质上使用的是深度搜索策略,所以一般可以使用递归的方法来实现。在搜索过程中,对本方有利的搜索点上应该取极大值,而对本方不利的搜索点上应该取极小值。 
极小值和极大值都是相对而言的。 
在搜索过程中需要合理的控制搜索深度,搜索的深度越深,效率越低,但是一般来说,走法越好。


#include <iostream>
using namespace std;
#define inf 100000000
int state[5][5],chess,xi,xj;
char ch;
int minfind(int,int,int);
int maxfind(int,int,int);
bool over(int x,int y) {
     bool flag = false;
     int row[5],col[5];
     memset(row,0,sizeof(row));
     memset(col,0,sizeof(col));
     for (int i=0;i<4;i++)
         for (int j=0;j<4;j++) {
             if (state[i][j]=='x') {
                row[i]++;
                col[j]++;
             }
             if (state[i][j]=='o') {
                row[i]--;
                col[j]--;
             }
         }
     if (row[x]==-4 || row[x]==4 || col[y]==-4 || col[y]==4) 
        flag = true;
     int tot1 = 0, tot2 = 0;
     for (int i=0;i<4;i++) {
         if (state[i][i]=='x') tot1++;
         if (state[i][3-i]=='x') tot2++;
         if (state[i][i]=='o') tot1--;
         if (state[i][3-i]=='o') tot2--;
     }
     if ((tot1==4 || tot1==-4) && x==y)        flag = true;
     if ((tot2==4 || tot2==-4) && x==3-y)      flag = true;
     return flag;
} 
int maxfind(int x,int y,int mini) {
    int tmp, maxi = -inf;
	if (over(x,y)) return maxi;
	if (chess==16) return 0;
	for (int i=0;i<4;i++)
	    for (int j=0;j<4;j++)
            if (state[i][j]=='.') {
                       state[i][j]='x';
                       chess++;
                       tmp = minfind(i,j,maxi);
                       chess--;
                       state[i][j]='.';
                       maxi = max(maxi, tmp);
                       if (maxi>=mini) return maxi;
            }
    return maxi;
}
int minfind(int x,int y,int maxi) {
    int tmp, mini = inf;
	if (over(x,y)) return mini;
	if (chess==16) return 0;
	for (int i=0;i<4;i++)
	    for (int j=0;j<4;j++)
            if (state[i][j]=='.') {
                       state[i][j]='o';
                       chess++;
                       tmp = maxfind(i,j,mini);
                       chess--;
                       state[i][j]='.';
                       mini = min(mini, tmp);
                       if (mini<=maxi) return mini;
            }
    return mini;
}
bool tryit() {
     int tmp, maxi = -inf;
     for (int i=0;i<4;i++)
         for (int j=0;j<4;j++)
             if (state[i][j]=='.') {
                state[i][j] = 'x';
                chess++;
                tmp = minfind(i,j,maxi);
                chess--;
                state[i][j] = '.';
                if (tmp>=maxi) {
                       maxi = tmp;
                       xi = i; xj = j;
                }
	            if (maxi==inf) return true;
             }
     return false;
}
int main() {
	while (scanf("%c",&ch)) {
		if (ch=='$') break;
		scanf("%c",&ch);

		chess = -4;
		for (int i=0;i<4;i++)
			for (int j=0;j<5;j++) {
				scanf("%c",&state[i][j]);
				chess += state[i][j]!='.';
			}
		if (chess<=4) {  //强力剪枝 
                      printf("#####\n");
                      continue;
        }
        if (tryit()) printf("(%d,%d)\n",xi,xj);
        else printf("#####\n");
	}
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值