棋盘游戏(信息学奥赛一本通-T1451)
生活随笔
收集整理的這篇文章主要介紹了
棋盘游戏(信息学奥赛一本通-T1451)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【題目描述】
在一個 4×4 的棋盤上有 8 個黑棋和 8 個白棋,當且僅當兩個格子有公共邊,這兩個格子上的棋是相鄰的。移動棋子的規則是交換相鄰兩個棋子。
給出一個初始棋盤和一個最終棋盤,請找出一個最短的移動序列使初始棋盤變為最終棋盤。
【輸入】
前四行,每行 4 個數字(1 或者 0 ),描述了初始棋盤;
接著是一個空行;
第六到第九行,每行 4 個數字(1 或者 0),描述了最終棋盤。
【輸出】
一行是一個整數 n,表示最少的移動步數。
【輸入樣例】
1111
0000
1110
0010
1010
0101
1010
0101
【輸出樣例】
4
思路:
本題是要從一個大狀態變到另一個大狀態,并且求其最小步數,很容易看出應用 BFS 來做
可以看出,每個單元非 0 即 1,共有 16 個單元,這樣可以將每個棋盤當做一個 16 位的二進制數,將其轉為十進制后再存儲狀態,最多有 2^16=65535 種狀態
對于每種狀態,由高到低枚舉每個位置,計算該位置在棋盤上的坐標 (x,y),理論上來說,格子可與其上下左右相鄰的四個格子任意進行交換,但顯然,但采用異或運算交換兩個相鄰格子時,對每個格子四方向的枚舉互換會造成大量的重復,因此,只要對每個格子從上到下,從左到右去嘗試互換即可
【源程序】
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<bitset> #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LL long long #define Pair pair<int,int> LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; } LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL res=0; while(b){if(b&1)res=(res+a)%mod; a=(a<<=1)%mod; b>>=1; } return res%mod;} LL quickMultPowMod(LL a, LL b,LL mod){ LL res=1,k=a; while(b){if((b&1))res=multMod(res,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return res%mod;} LL quickPowMod(LL a,LL b,LL mod){ LL res=1; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1; } return res; } LL getInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); } LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); } LL LCM(LL x,LL y){ return x/GCD(x,y)*y; } const double EPS = 1E-6; const int MOD = 1000000000+7; const int N = 1000+5; const int dx[] = {0,0,-1,1,1,-1,1,1}; const int dy[] = {1,-1,0,0,-1,1,-1,1}; using namespace std;struct Node {int val;int step;Node() {}Node(int val, int step) : val(val), step(step) {} }; int vis[65536 + 10]; void BFS(Node st, Node ed) {memset(vis, 0, sizeof(vis));queue<Node> Q;Q.push(st);while (!Q.empty()) {Node now = Q.front();Q.pop();if (now.val == ed.val) {cout << now.step << endl;return;}int val = now.val;int step = now.step;for (int i = 15; i >= 0; i--) { //從高到低枚舉每一位int x = (15 - i) / 4, y = (15 - i) % 4; //橫縱坐標int nowPos = 1 << i; //當前位置代表權值int rightPos = 1 << (i - 1); //當前位置右方位置代表權值int downPos = 1 << (i - 4); //當前位置下方位置代表權值if (y < 3 && ((val & nowPos) != (val & rightPos))) { //向右交換int nextVal = val ^ nowPos ^ rightPos; //交換后的狀態if (!vis[nextVal]) {vis[nextVal] = true;Q.push(Node(nextVal, step + 1));}}if (x < 3 && ((val & nowPos) != (val & downPos))) { //向下交換int nextVal = val ^ nowPos ^ downPos; //交換后的狀態if (!vis[nextVal]) {vis[nextVal] = true;Q.push(Node(nextVal, step + 1));}}}} } int main() {char ch;int st = 0, ed = 0;for (int i = 15; i >= 0; i--) {cin >> ch;if (ch == '1')st += 1 << i;}for (int i = 15; i >= 0; i--) {cin >> ch;if (ch == '1')ed += 1 << i;}if (st == ed)printf("0\n");elseBFS(Node(st, 0), Node(ed, 0));return 0; }?
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的棋盘游戏(信息学奥赛一本通-T1451)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 悼念512汶川大地震遇难同胞——珍惜现在
- 下一篇: 理论基础 —— 栈 —— 双端栈