四子連棋
阿新 • • 發佈:2018-11-06
爆搜!爆搜!爆搜!爆搜!爆搜!
先看題目
題目描述
在一個4*4的棋盤上擺放了14顆棋子,其中有7顆白色棋子,7顆黑色棋子,有兩個空白地帶,任何一顆黑白棋子都可以向上下左右四個方向移動到相鄰的空格,這叫行棋一步,黑白雙方交替走棋,任意一方可以先走,如果某個時刻使得任意一種顏色的棋子形成四個一線(包括斜線),這樣的狀態為目標棋局。
● ○ ●
○ ● ○ ●
● ○ ● ○
○ ● ○
輸入輸出格式
輸入格式:
從檔案中讀入一個4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地帶用O表示。
輸出格式:
用最少的步數移動到目標棋局的步數。
輸入輸出樣例
輸入樣例#1:
BWBO
WBWB
BWBW
WBWO
輸出樣例#1:
5
乍一看,肯定是搜尋,應該要剪枝,不剪枝時間上恐怕過不去,這怎麼做,沒思路,不會,我太弱了,我怎麼這麼弱,自閉。。。
仔細想想,直接dfs會怎樣,怎麼樣也會騙點分吧,(嗯,這題可做)扶我起來,我還要打程式碼!!!再仔細想想每次每個空格周圍有4種走法,所以最多也就8種走法,4*4的棋盤,好像完全可以,(不能自閉,站起來A了這題!!!),當走14次的時候就會遍歷了整個棋盤,所以總步數不會超過14???還可以優化?,開敲!敲完後,滿心歡喜地測樣例,卻發現過不了樣例,這就很尷尬,實在沒辦法了,問學長吧,然後“一語驚醒夢中人”,黑白棋要交替下的!!!所以,記錄下移動的棋的顏色,下一次走的時候不走這種顏色的就可以了。
(看來遇到問題要多想想,不能自閉)。
貼程式碼:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; char pic[5][5]; int ans = 2147483647; int tx[9] = {0,1,-1,0,0}; int ty[9] = {0,0,0,1,-1}; //最原始判斷方法 int check(){ if(pic[1][1] == pic[1][2] && pic[1][2] == pic[1][3] && pic[1][3] == pic[1][4])return 1; if(pic[2][1] == pic[2][2] && pic[2][2] == pic[2][3] && pic[2][3] == pic[2][4])return 1; if(pic[3][1] == pic[3][2] && pic[3][2] == pic[3][3] && pic[3][3] == pic[3][4])return 1; if(pic[4][1] == pic[4][2] && pic[4][2] == pic[4][3] && pic[4][3] == pic[4][4])return 1; if(pic[1][1] == pic[2][1] && pic[2][1] == pic[3][1] && pic[3][1] == pic[4][1])return 1; if(pic[1][2] == pic[2][2] && pic[2][2] == pic[3][2] && pic[3][2] == pic[4][2])return 1; if(pic[1][3] == pic[2][3] && pic[2][3] == pic[3][3] && pic[3][3] == pic[4][3])return 1; if(pic[1][4] == pic[2][4] && pic[2][4] == pic[3][4] && pic[3][4] == pic[4][4])return 1; if(pic[1][1] == pic[2][2] && pic[2][2] == pic[3][3] && pic[3][3] == pic[4][4])return 1; if(pic[1][4] == pic[2][3] && pic[2][3] == pic[3][2] && pic[3][2] == pic[4][1])return 1; return 0; } void dfs(int t,char opt){ if(t > ans ||t > 14)return;//剪枝優化 if(check()){ ans = min(ans,t); return; } for(int i = 1; i<=4; i++){ for(int j = 1; j<=4; j++){ if(pic[i][j] == 'O'){ for(int k = 1; k<=8; k++){ int dx,dy; dx = i + tx[k]; dy = j + ty[k]; if(dx <= 4 && dx >=1 && dy <= 4 && dy >= 1 &&pic[dx][dy] != opt&& pic[dx][dy] != 'O'){ swap(pic[dx][dy],pic[i][j]);//cout<<dx <<' '<<dy<<'\n'; //cout<<i << ' ' << j << '\n'; dfs(t + 1,pic[i][j]);//傳的是移動步數,和該步所移動棋子的顏色 swap(pic[dx][dy],pic[i][j]); } } } } } return; } int main(){ for(int i = 1; i<=4; i++){ for(int j = 1; j<=4; j++){ cin >> pic[i][j]; } } if(check()){ cout<<1<<'\n'; return 0; } dfs(0,'O'); //if(ans == 1)ans = 0; cout << ans; return 0; }