廣度搜尋 POJ 1753

2021-05-31 21:30:16 字數 1956 閱讀 5023

題意:乙個4×4的棋盤,每個格仔放著乙個棋子。棋子一面是白色,一面是黑色。一次操作可以將某乙個格仔以及上下左右共5個格仔的棋子都翻過來,即白色變黑色,黑色變白色。現在給出一種棋盤狀態,問最少需要幾次操作可以將棋盤全部變為同種顏色。

輸入:sample input

bwwb

bbwb

bwwb

bwww

sample output

4

典型的廣搜題目:這裡把這道題的收穫寫在這裡,以便以後回顧:

首先是要明白spfa演算法:

演算法的流程其實與分層遍歷二叉樹的**差不多。

if (0 == t || (1<<16) - 1 == t) return 0;

memset(rec, 0, sizeof(rec)); memset(step, 0, sizeof(step));

queueq; q.push(t); step[t] = 0; rec[t] = 1;

while (!q.empty())

}} return -1;

flip的實現

inline void set(int &m, int i, int j)

inline void clr(int &m, int i, int j)

inline bool test(int &m, int i, int j)

inline void rever(int &m, int i, int j)

inline bool range(int i, int j)

void flip(int &m, int i, int j)

, , , };

for (int k = 0; k < 4; ++k)

}

後來發現對某一位取反,只要 n ^= (1 << i );就可以了。

實際上,如果對於0,1,兩位取異或則是 n ^= 3

那麼在翻動的過程中,翻動第乙個棋子時,應該與19取異或。

每一位應該與哪個數取異或可以由以下程式得到

#includeint main(void)

, , , };

int i, j, k, n, v;

int x, y;

for (i = 0; i < 16; ++i)

}printf("%d,", n);

}return 0;

}

那麼在在翻某一位時,可以把**更改如下:

q[++tail] = t; rec[t] = 1;

while (head != tail)

}} return -1;

輸入的處理

如果分開輸入,那麼輸入之後,還要把字串接起來,有沒有什麼辦法直接得到整個字串,偶然得到下面這個方法比較好使

char str[15];

scanf("%s%s%s%s", str, str + 4, str + 8, str + 12);

輸入之後,你再輸出str試試

**寫得一般,湊合著看吧,我比較喜歡把**寫得短一點。

#include#include#includeint flip = ;

char rec[1<<16];

int step[1<<16];

int q[1<<18];

int bfs(int t)

} }return -1;

}char str[40];

static int getn(char *s)

return n;

}int main(void)

POJ1753 棋盤翻轉(位壓縮 廣度優先搜尋)

題目大意 有乙個4 4的方格,每個方格中放一粒棋子,這個棋子一面是白色,一面是黑色。遊戲規則為每次任選16顆中的一顆,把選中的這顆以及它四周的棋子一併反過來,當所有的棋子都是同乙個顏色朝上時,遊戲就完成了。現在給定乙個初始狀態,要求輸出能夠完成遊戲所需翻轉的最小次數,如果初始狀態已經達到要求輸出0。...

poj 1753 位壓縮 搜尋

題意 有乙個4 4的方格,每個方格中放一粒棋子,這個棋子一面是白色,一面是黑色。遊戲規則為每次任選16顆中的一顆,把選中的這顆以及它四周的棋子一併反過來,當所有的棋子都是同乙個顏色朝上時,遊戲就完成了。現在給定乙個初始狀態,要求輸出能夠完成遊戲所需翻轉的最小次數,如果初始狀態已經達到要求輸出0。如果...

poj1753 搜尋,列舉法

1 2014.3.1 2 poj175334 5 題意 6 給你乙個4 4的黑白棋盤,通過翻棋子使棋盤變為全白或全黑,7 以下 翻乙個位置 皆指翻著個位置和它周圍的四個棋子。8 翻子時四周的四個棋子如果存在的話顏色也會跟著改變。9 問最少需要多少步可以使棋盤變為一種顏色。10 11 思路 12 每一...