這是一個縱橫火柴棒遊戲。如圖[1.jpg],在一個3x4的方格中,遊戲的雙方輪流放置火柴棒。其規則是:
1. 不能放置在已經放置火柴棒的地方(即只能在空格中放置)。
2. 火柴棒的方向只能是垂直或水平放置。
3. 火柴棒不能與其它格子中的火柴“連通”。所謂連通是指兩根火柴棒可以連成一條直線,且中間沒有其它不同方向的火柴“阻攔”。
例如:圖[1.jpg]所示的局面下,可以在C2位置豎直放置,但不能水平放置,因爲會與A2連通。同樣道理,B2,B3,D2此時兩種方向都不可以放置。但如果C2豎直放置後,D2就可以水平放置了,因爲不再會與A2連通(受到了C2的阻擋)。
4. 遊戲雙方輪流放置火柴,不可以棄權,也不可以放多根。直到某一方無法繼續放置,則該方爲負(輸的一方)。
遊戲開始時可能已經放置了多根火柴。
你的任務是:編寫程序,讀入初始狀態,計算出對自己最有利的放置方法並輸出。
00-1
-000
0100
即用“0”表示空格位置,用“1”表示豎直放置,用“-”表示水平放置。
【輸入、輸出格式要求】
用戶先輸入整數 n(n<100), 表示接下來輸入 n 種初始局面,每種局面佔3行(多個局面間沒有空行)。
程序則輸出對應的每種初始局面,計算出的最佳走法(行號+列號+放置方式)。
例如:用戶輸入:
2
0111
-000
-000
1111
----
0010
則程序可以輸出:
00-
211
輸出結果的含義爲:
對第一個局面,在第0行第0列水平放置
對第二個局面,在第2行第1列垂直放置
注意:
行號、列號都是從0開始計數的。
對每種局面可能有多個最佳放置方法(解不唯一),只輸出一種即可。
例如,對第一個局面,001 也是正解;最第二個局面,201也是正解。
#include<iostream>
using namespace std;
char grid[3][4];
char type[]={'1','-'};
bool isPositon(int x,int y,char c)//判斷該位置是否可以放
{
if(c=='1')//1有兩種情況不能放,上下都不能爲1,但可以用-隔開
{
for(int i=x-1;i>=0;i--)
{
if(grid[i][y]==c)
return false;
else
break;
}
for(int i=x+1;i<3;i++)
{
if(grid[i][y]==c)
return false;
else
break;
}
}
else //-也有兩種情況,左右不能爲-,但可以用1隔開
{
for(int j=y-1;j>=0;j--)
{
if(grid[x][j]=='-')
return false;
else break;
}
for(int j=y+1;j<4;j++)
{
if(grid[x][j]=='-')
return false;
else break;
}
}
return true;
}
bool isWin(int x,int y,char c)//判斷在(x,y)放c能不能贏
{
if(!isPositon(x,y,c))//不能放
return false;
else
{
//枚舉當前情況下,對方有沒有贏的可能
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
if(grid[i][j]=='0')
{
for(int k=0;k<2;k++)
{
grid[i][j]=type[k];
if(isWin(i,j,type[k]))//對方能贏
{
grid[i][j]='0';
return false;//我們就不能贏
}
grid[i][j]='0';
}
}
}
}
return true;//能贏
}
}
void Judge()
{
//枚舉可以放的情況
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
if(grid[i][j]=='0')
{
for(int k=0;k<2;k++)
{
grid[i][j]=type[k];
if(isWin(i,j,type[k]))//放該位置能贏
{
cout<<i<<' '<<j<<' '<<type[k]<<endl;
return ;
}
grid[i][j]='0';
}
}
}
}
}
int main()
{
int n;
cin>>n;
while(n--)
{
//輸入數據
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
cin>>grid[i][j];
}
}
//枚舉
Judge();
}
}