poj 1568極小探索

3610 ワード

質問:4 x 4 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("#####
"); continue; } if (tryit()) printf("(%d,%d)
",xi,xj); else printf("#####
"); } return 0; }