藍橋杯 方塊填數 DFS搜尋

2021-06-29 02:48:52 字數 3832 閱讀 5857

「數獨」是當下炙手可熱的智力遊戲。一般認為它的起源是「拉丁方塊」,是大數學家尤拉於2023年發明的。

如圖[1.jpg]所示:6x6的小格被分為6個部分(圖中用不同的顏色區分),每個部分含有6個小格(以下也稱為分組)。

開始的時候,某些小格中已經填寫了字母(abcdef之一)。需要在所有剩下的小格中補填字母。

全部填好後,必須滿足如下約束:

1. 所填字母只允許是a,b,c,d,e,f 中的某乙個。

2. 每行的6個小格中,所填寫的字母不能重複。

3. 每列的6個小格中,所填寫的字母不能重複。

4. 每個分組(參見圖中不同顏色表示)包含的6個小格中,所填寫的字母不能重複。

為了表示上的方便,我們用下面的6階方陣來表示圖[1.jpg]對應的分組情況(組號為0~5):

000011

022013

221113

243333

244455

445555

用下面的資料表示其已有字母的填寫情況:

02c03b

05a20d

35e53f

很明顯,第一列表示行號,第二列表示列號,第三列表示填寫的字母。行號、列號都從0開始計算。

一種可行的填寫方案(此題剛好答案唯一)為:

e f c b d a

a c e d f b

d a b e c f

f b d c a e

b d f a e c

c e a f b d

你的任務是:編寫程式,對一般的拉丁方塊問題求解,如果多解,要求找到所有解。

【輸入、輸出格式要求】

使用者首先輸入6行資料,表示拉丁方塊的分組情況。

接著使用者輸入乙個整數n (n<36), 表示接下來的資料行數

接著輸入n行資料,每行表示乙個預先填寫的字母。

程式則輸出所有可能的解(各個解間的順序不重要)。

每個解占用7行。

即,先輸出乙個整數,表示該解的序號(從1開始),接著輸出乙個6x6的字母方陣,表示該解。

解的字母之間用空格分開。

如果找不到任何滿足條件的解,則輸出「無解」

例如:使用者輸入:

000011

022013

221113

243333

244455

445555

602c

03b05a

20d35e

53f則程式輸出:

1e f c b d a

a c e d f b

d a b e c f

f b d c a e

b d f a e c

c e a f b d

再如,使用者輸入:

001111

002113

022243

022443

544433

555553

704b

05a13d

14c24e

50c51a

則程式輸出:

1d c e f b a

e f a d c b

a b f c e d

b e d a f c

f d c b a e

c a b e d f

2d c e f b a

e f a d c b

a d f b e c

b e c a f d

f b d c a e

c a b e d f

3d c f e b a

a e b d c f

f d a c e b

b f e a d c

e b c f a d

c a d b f e

4d c f e b a

b e a d c f

a d c f e b

f b e a d c

e f b c a d

c a d b f e

5d c f e b a

e f a d c b

a b c f e d

b e d a f c

f d b c a e

c a e b d f

6d c f e b a

e f a d c b

a b d f e c

b e c a f d

f d b c a e

c a e b d f

7d c f e b a

e f a d c b

a d b f e c

b e c a f d

f b d c a e

c a e b d f

8d c f e b a

f e a d c b

a d b c e f

b f e a d c

e b c f a d

c a d b f e

9d c f e b a

f e a d c b

a f c b e d

b d e a f c

e b d c a f

c a b f d e

一、首先,如果要是搜尋圖,我們必須知道下一步(第一步)要搜尋什麼地方,觀察題目,可以看出,題目中要求填完之後每行每列每個區域內的字母都不相同,很明顯,如果一行(一列)中的字母越多,那麼我們越容易確定剩下的地方該填入什麼字母,基於這個出發點,我們約定,程式每次都會尋找這樣乙個點:它所在的行和所在的列中的字母數量之和最多,並且這個位置還是空的,這樣的位置可能不止乙個,那我們取第乙個遇到的。為了完成這個運算,我們設定hor和ver兩個陣列分別記錄每一行和每一列所含字母的個數。

二、當找到要填入字母的位置後,我們又會遇到乙個新的問題,這個位置到底能填入哪些字母呢?根據題意,我們先設定乙個標誌位useful,表示a-f六個字母哪個是可用的,然後分別對這個點所在的行,所在的列和所在的區域進行掃瞄,只要是出現過的字母,自然就不能再次出現了。這裡說一下掃瞄區域的方法:因為題目給出的資料對於區域的描述是用0-5六個數字標記的,我們要利用這個特點,設定乙個陣列

area_used[i][j],表示第i個區域中j+'a'這個字母是否是用過,利用這個陣列,我們就可以很方便的對每個區域中所含字母的情況進行統計了

三、當找到了位置,找到了哪些可以填入的字母,就可以進行遞迴填字母了,每次填完乙個字母,就進入下一層遞迴,遞迴的出口是所有字母的數量,當達到36的時候自然就找到了一組符合題目要求的解。

#include#include#includeusing namespace std;

char map[6][6];//儲存區域分布的那組資料

char result[6][6];//儲存最終結果,裡面是字母

int hor[6],ver[6];//儲存每行和每列中所含字母的數量

int last,cas;//儲存還剩下幾個字母要填,以及解的數量

bool area_used[6][6];//標誌每個區域中是否所含某個字母 area_used[i][j]=true標誌第i個區域含有j+'a'這個字母

void getmap()//輸入資料 }

void init()//初始化

void showresult()//輸出結果

}}

} hor[r]++;

ver[c]++;

for(i=0;i<6;i++)//查詢這個位置可以填入哪些字母

for(i=0;i<6;i++)//迴圈將可以填入的字母分別嘗試填入 }

hor[r]--;

ver[c]--;

result[r][c]='*';//結果矩陣中填入的字母去掉

last++;

}int main()

藍橋杯方格填數DFS

如下的10個格仔 如果顯示有問題,也可以參看 圖1.jpg 填入0 9的數字。要求 連續的兩個數字不能相鄰。左右 上下 對角都算相鄰 一共有多少種可能的填數方案?請填寫表示方案數目的整數。注意 你提交的應該是乙個整數,不要填寫任何多餘的內容或說明性文字。題目要求一點與和它相鄰的8個點都不相差1 in...

藍橋杯決賽之方塊填數

程式設計題 滿分33分 數獨 是當下炙手可熱的智力遊戲。一般認為它的起源是 拉丁方塊 是大數學家尤拉於1783年發明的。如圖 1.jpg 所示 6x6的小格被分為6個部分 圖中用不同的顏色區分 每個部分含有6個小格 以下也稱為分組 開始的時候,某些小格中已經填寫了字母 abcdef之一 需要在所有剩...

藍橋杯 方塊填數 數獨 dfs 狀壓 c

數獨 是當下炙手可熱的智力遊戲。一般認為它的起源是 拉丁方塊 是大數學家尤拉於1783年發明的。如圖 1.jpg 所示 6x6的小格被分為6個部分 圖中用不同的顏色區分 每個部分含有6個小格 以下也稱為分組 開始的時候,某些小格中已經填寫了字母 abcdef之一 需要在所有剩下的小格中補填字母。全部...