1. 程式人生 > 其它 >題解0008:棋盤遊戲

題解0008:棋盤遊戲

題目連結:http://ybt.ssoier.cn:8088/problem_show.php?pid=1451

(信奧一本通1451)

題目描述:輸入倆棋盤(4*4),一半黑子(1)一半白子(0),兩個棋子可以交換,問第一個棋盤要交換多少次才能變成第二個。

題目思路:

廣搜,先找出兩個棋盤的不同,再兩兩交換,最後求出步數

但是要是用2維陣列模擬的話肯定超時,所以我們要優化一下

我們可以用位運算,將棋盤轉成一串2進位制數,再轉化成10進位制存起來

這樣就只用判斷兩個陣列了,大大縮短時間

(具體詳見程式碼註釋)

#include<bits/stdc++.h>

using namespace std;
struct Q{
	int a,b;
};//存在佇列裡的結構體,a是二進位制狀態的當前棋盤,b是步數 
int A,B,arr[1000000]={0};//判斷一個位置是否交換過 
void bfs(){
	queue<Q> q;
	q.push((Q){A,0});//將初始棋盤塞入佇列,清零步數 
	while(!q.empty()){
		Q u=q.front();
		q.pop();
		int temp=u.a;
		if(temp==B){//如果交換後的棋盤與最終棋盤重合證明找到了,輸出結束 
			cout<<u.b;
			return;
		}
		for(int i=15;i>=0;i--){
			int x=(15-i)%4;
			int y=(15-i)/4;
			//找棋盤某位置在陣列狀態的x和y座標
			int z=(1<<i); 
			int r;
			if(x<3&&(temp&(1<<i))!=(temp&(1<<i-1))){//判斷左右能不能換
               //(x>3是為了不讓第一排最後一個和第二排第一個交換) r=(1<<i-1); if(arr[temp^z^r]==0){//判斷有沒有交換過 arr[temp^z^r]=1; q.push((Q){temp^z^r,u.b+1});//交換棋盤,步數+1 } } if(y<3&&(temp&(1<<i))!=(temp&(1<<i-4))){//判斷左右能不能換(上下差4個) r=(1<<i-4); if(arr[temp^z^r]==0){//判斷有沒有交換過 arr[temp^z^r]=1; q.push((Q){temp^z^r,u.b+1});//交換棋盤,步數+1 } } } } } int main(){ char p;//要一個一個單數存,所以用char int i; for(i=15;i>=0;i--){ cin>>p; A+=(p-'0')*1<<i;//用十進位制表示二進位制數存棋盤 }