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.
![](https://i-blog.csdnimg.cn/blog_migrate/0bb07a1914e231c7a24b6849724bcbeb.gif)
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
*/