2015
05-23

# DUIDUI Bang

You are given an 8 by 8 chessboard and five different kinds of pawn. The rule is simple; you can only swap two adjacent pawns. After the swap, if there are three or more consecutive identical pieces either horizontally or vertically, they will be eliminated. After that, the pawn will fall down to fill the empty grids. The empty grids that no pawn fills will be filled by randomly picked pawn from top edge. Sometimes you may be lucky enough to have the pawn eliminated automatically according to the rules above. In addition, if there is one move leads to eight or more than eight pawn to be eliminated, the player will be granted a combo. A smart guy as you are, could you please tell us what is the maximum possibility to trigger a combo in one swap?

In the figure, for example, swap the blue gem and the purple star will ensure a combo. Because, this will cause the red gem fall down and eliminated. The yellow gems will disappear after the red ones.

The first line contains a single integer t, the number of test cases.
For each case, 8 lines contain pawn data. See sample input for more details.

The first line contains a single integer t, the number of test cases.
For each case, 8 lines contain pawn data. See sample input for more details.

2

10112344
13213241
30404021
31104204
23221011
02041200
14102122
22330443

13143243
42422004
11012130
34400104
03142423
21220441
01021133
43044200

Case #1: 1.000
Case #2: 0.525

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

#define N 8
#define exp 1e-8
using namespace std;

int map[N][N];
int vis[N][N];
int x[]={0,1};
int y[]={1,0};
char str[20];

inline void balance(int mt[N][N]){
int i,j,k;
for (i=0;i<N;i++)
for (j=N-1;j>=0;j--)
if (mt[j][i]==-1){
for (k=j-1;k>=0;k--)
if (mt[k][i]!=-1) break;
if (k<0) break;
swap(mt[k][i],mt[j][i]);
}
}
inline int get(int mt[N][N]){
memset(vis,0,sizeof(vis));
int i,j,sum=0;
for (i=0;i<N;i++)
for (j=0;j<N;j++){
if (j+2<N&&mt[i][j]==mt[i][j+1]&&mt[i][j]==mt[i][j+2])
vis[i][j]=vis[i][j+1]=vis[i][j+2]=1;
if (i+2<N&&mt[i][j]==mt[i+1][j]&&mt[i][j]==mt[i+2][j])
vis[i][j]=vis[i+1][j]=vis[i+2][j]=1;
}
for (i=0;i<N;i++)
for (j=0;j<N;j++)
if (vis[i][j]) {mt[i][j]=-1;sum++;}
if (sum>0) balance(mt);
return sum;
}

double work(int mtp[N][N],int num){
int i,j;
int mt[N][N];
for (i=0;i<N;i++)
for (j=0;j<N;j++)
mt[i][j]=mtp[i][j];
int su=get(mt);
if (su==0) return 0.0;
if (num+su>=8) return 1.0;
num=num+su;
vector < pair <int,int> > pi;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
if (mt[i][j]==-1) pi.push_back( make_pair(i,j));
int zz =1;
for (i=0;i<pi.size();i++)   zz=zz*5;
double fm=zz;
double ans=0;
for (int t=0;t<zz;t++){
int p=t;
for(int i=0;i<pi.size();i++){
mt[pi[i].first][pi[i].second]=p%5;
p/=5;
}
ans +=work(mt,num);
}
return ans/fm;
}

inline double dfs(){
double ans=0,gs;
int i,j,k,t,l;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
for (k=0;k<2;k++){
if (i+x[k]<N&&j+y[k]<N){
swap(map[i][j],map[i+x[k]][j+y[k]]);
gs=work(map,0);
swap(map[i][j],map[i+x[k]][j+y[k]]);
ans=max(ans,gs);
if (1-ans<exp) goto end;
}
}
end: return ans;
}
inline void init(){
int i,j;
for (i=0;i<N;i++){
scanf("%s",str);
for (j=0;j<N;j++)
map[i][j]=str[j]-'0';
}
}

int main(){
int test;
scanf("%d",&test);
for (int cas=1;cas<=test;cas++){
init();
printf("Case #%d: %.3lf\n",cas,dfs());
}
return 0;
}