P1074 靶形數獨 題解

2021-10-07 10:45:21 字數 3040 閱讀 5293

原題傳送門

不愧是 2009 noip tg t4 ,連續打了4天的**,吸了口氧才通過。

前置知識:

對於一道數獨題,我們可以先預處理出每一行0的個數,然後從個數最少的行開始做,這樣可以節省大量的時間(因為這些格仔可以填的數字少)。

對於本題,我一開始的思路是:仿照前置知識預處理,分數進行打表,存在 poi

nt

point

poin

t 陣列裡面,用下列的三個函式進行填數之後的標記處理(這裡我令 ai,

j,ka_

ai,j,k

​ 為第 (i,

j)

(i,j)

(i,j

) 的格仔能否填數字 k

kk ), dfs 填表時按照去處理,部分**如下:

//分數打表自動略去

//b陣列是我用來存放數獨的陣列

//以下是預處理**

struct

node

sum[maxn]

;void

getshun()

sort

(sum+

1,sum+9+

1,cmp);}

//獲知應該搜尋的行,將其存在sum結構體中

void

getc()

}}//獲取每乙個點所在的九宮格,nx,ny陣列表示每乙個宮格左上角與右下角的座標,0為左上角,1為右下角

void

deal

(int x,

int y)

//做標記

void

redeal

(int x,

int y)

//恢復現場

//對於每個關鍵陣列和變數的意義在全部**中會詳細給出,想知道的讀者可以先看全部**再返回

結果樣例測完後就發現,這種方法極其不穩定,很容易在 dfs 時序列(這行還沒搜尋完就到下一行),所以我們要想乙個更穩定的方法。

實際上,如果吸口氧前面的預處理已經足夠優秀了,關鍵是如何決定搜尋順序。

行如果不穩定,那麼按列搜???好像差不多

等等,好像除了行和列,還有點吧!!!

所以我決定按點搜。

我在**中新開了乙個陣列(結構體) dfs

rdfsr

dfsr

,用來存放搜點的順序,其中 tmp

tmptm

p 是零點的數量(對上面**中的 get

cgetc

getc

無影響),處理時還是按照 sum

sumsu

m 陣列進行處理,從最少的行開始依次存0點,然後進行搜尋。這樣,吸口氧就能過去了。

注意本題細節問題很多,並且很容易因為按行搜而困住(如果您按行搜過了那您就太厲害了, orz )

全部**如下:

#

include

using

namespace std;

const

int maxn=9+

5;int a[maxn]

[maxn]

[maxn]

,b[maxn]

[maxn]

,c[maxn]

[maxn]

;//b:存放數獨的陣列 a:a[i][j][k]表示(i,j)能否填數字k,c:c[i][j]表明(i,j)所在的宮格

int nx[maxn][2

]=,,

,,,,

,,,}

;int ny[maxn][2

]=,,

,,,,

,,,}

;//nx,ny:nx,ny陣列表示每乙個宮格左上角與右下角的座標,0為左上角,1為右下角

int point[maxn]

[maxn]=,

,,,,

,,,,

};//point:分數的打表

int ans=-1

,tmp;

//ans為答案,初始值為-1可以方便後續答案的統計,tmp是0點的個數

struct

node

sum[maxn]

;//sum:處理行的順序,x=第x行,num=該行0點個數

struct

node2

dfsr[maxn*

100]

;//dfsr:處理0點的搜尋順序

bool

cmp(

const node& fir,

const node& sec)

//對sum陣列按照0點個數公升序排序

void

getshun()

sort

(sum+

1,sum+9+

1,cmp);}

//處理sum陣列

void

getzero()

}}return;}

//處理dfsr陣列

void

getc()

}}//處理c陣列

void

deal

(int x,

int y)

//做標記

void

redeal

(int x,

int y)

//恢復現場

intmax

(int fir,

int sec)

void

getanswer()

ans=

max(ans,getans);}

//獲取ans

void

dfs(

int k)

for(

int i=

1;i<=

9;i++)}

}//按點搜尋,k為第k個0點

intmain()

dfs(1)

;printf

("%d\n"

,ans)

;return0;

}

題解 P1074 靶形數獨

看完所有的題解之後發現沒有人用二進位制,我就知道我的機會來了 手動滑稽 x y 相當於x pow 2,y lowbit x 找到x的二進位制中最小的1的位置1 1 10 1 0 0 0 0 沒有了關於這一題,line,rool,cell三個陣列 均初始化為111111111 二進位制 分別用來存這一...

題解 P1074 靶形數獨

來一篇通俗點的dlx的題解。有關dlx的講解 針對本題的一些細節詳見注釋。code include include includeusing namespace std const int maxn 81 4 5 const int maxnode 9 9 9 4 4 5 const int slo...

P1074 靶形數獨

小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他們想用數獨來一比高低。但普通的數獨對他們來說都過於簡單了,於是他們向 z 博士請教,z 博士拿出了他最近發明的 靶形數獨 作為這兩個孩子比試的題目。靶形數獨的方格同普通數獨一樣,在 999 格寬 999 格高的大九宮格中有 ...