poj3317 Stake Your Claim极大极小

Stake Your Claim
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 1010 Accepted: 357

Description

The designers at Gazillion Games Inc. have come up with a new, relatively simple game called "Stake Your Claim". Two players – 0 and 1 – initially select two values n and m and an n × n board is created with m 0's and m 1's randomly placed on the board. Starting with player 0, each player puts his/her number in one of the empty squares on the board. After the board is filled, each player's score is equal to the largest connected region on the board filled with that player's number (where a connected region is one where for any two squares in the region a path exists consisting of only N/S/E/W moves). The player with the highest score wins, and is awarded the difference between his/her score and the score of the other player. Two examples of finished games are shown below, with the largest connected regions for each player outlined. Note in the second example that the two sections with 2 0's each are not connected.

In order to test how good this game is, the gang at Gazillion has hired you to write a program which can play the game. Specifically, given any starting configuration, they would like a program to determine the best move for the current player, i.e., the score which maximizes the points awarded to that player (or minimizes those awarded to the player's opponent).

Input

Input will consist of multiple test cases. Each test case will start with a line containing a positive integer n (≤ 8) indicating the size of the board. Next will come n lines describing the current board layout (row 0 first, followed by row 1, etc). Each of these lines will contain n characters taken from '0', '1' and '.', where '.' represents an empty square. The first character will be in column 0, the second in column 1, etc. The number of 0's on the board will either be equal to the number of 1's or one greater, and there will be between 1 and 10 (inclusive) empty squares. The last case is followed by a line containing 0 which indicates end-of-input and should not be processed.

Output

For each test case, output a single line containing two items: the coordinates of the best move for the player and the best point total achieved by that player. In case of ties, print the move which comes first lexicographically. Use the format shown in the sample output.

Sample Input

4
01.1
00..
.01.
...1
4
0.01
0.01
1..0
.1..
0

Sample Output

(1,2) 2
(2,2) -1

Source

 

 

 

 

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf=(1<<30);
const int N=25;
int pw2[25],pw3[25];
map<int,int>rpw2;

struct point {
    int x,y;
}pt[N];
int n,m;
char g[N][N];
int ansx,ansy,score;
int ans[N],ct;
int hash[555555];
bool vis[10][10];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int tt;
void dfs(int x,int y,char ch)
{
    if(vis[x][y]) return ;
    vis[x][y]=true;tt++;
    for(int i=0;i<4;i++)
    {
        int pi=x+dir[i][0];int pj=y+dir[i][1];
        if(pi<0||pi>=n||pj<0||pj>=n) continue;
        if(g[pi][pj]==ch)
        dfs(pi,pj,ch);
    }
}
int check()
{
    memset(vis,false,sizeof(vis));
    int c1=0,c2=0;
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        tt=0;
        if(!vis[i][j])
        dfs(i,j,g[i][j]);
        if(g[i][j]=='0') c1=max(c1,tt);
        else c2=max(c2,tt);
    }
    return c1-c2;
}
int maxmin(int state,int who,int now,int alpha,int beta,int dep) {
    if(state==0)
    {
        for(int i=0;i<dep;i++)
        {
            int x=ans[i];
            g[pt[x].x][pt[x].y]=(i&1)+'0';
        }
        int tep=check();
        return tep;///
    }
    if(hash[now]!=-inf) return hash[now];
    int maxval=-inf,minval=inf,val;
    for(int st=state;st;st-=st&(-st))
    {
        int i=st&(-st),x=rpw2[i];
        ans[dep]=x;///
        val=maxmin(state-i,who^1,now+(who+1)*pw3[x],maxval,minval,dep+1);
        if(who==0&&val>beta) return val;
        if(who==1&&val<alpha) return val;
        maxval=max(maxval,val);
        minval=min(minval,val);

        if(dep==0) {
            if(maxval>score||(maxval==score&&(ansx>pt[x].x||(ansx==pt[x].x&&ansy>pt[x].y)))) {
                score=maxval;
                ansx=pt[x].x; ansy=pt[x].y;
            }
        }
    }
    if(who==0) return hash[now]=maxval;
    else return hash[now]=minval;
}
void init() {
    pw2[0]=pw3[0]=1;
    for(int i=0;i<20;i++) pw2[i]=1<<i,rpw2[1<<i]=i;
    for(int i=1;i<20;i++) pw3[i]=pw3[i-1]*3;
}

int main()
{
    int i,j,t,cas=0;
    int st,ct1,ct2;
    init();
    while(scanf("%d",&n)&&n)
    {
        ct1=ct2=m=0;
        for(i=0;i<n;i++) {
            scanf("%s",g[i]);
            for(j=0;j<n;j++) {
                if(g[i][j]=='.')pt[m].x=i,pt[m++].y=j;
                else if(g[i][j]=='0') ct1++;
                else ct2++;
            }
        }
        if(ct1>ct2)
        {
            for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            if(g[i][j]=='0') g[i][j]='1';
            else if(g[i][j]=='1') g[i][j]='0';
        }
        st=pw2[m]-1; //111111
        score=-inf;///
        for(i=0;i<pw3[m];i++) hash[i]=-inf;
        //ansx=inf;///
        int ret=maxmin(st,0,0,-inf,inf,0);
        //if(ret==0) puts("#####");
        printf("(%d,%d) %d\n",ansx,ansy,ret);
    }
    return 0;
}

/*
4
01.1
00..
.01.
...1
4
0.01
0.01
1..0
.1..
0
*/


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值