一本通 洛谷 靶型數獨 題解

2022-04-12 02:02:40 字數 2363 閱讀 7816

題目傳送

主要是搜尋順序不同導致效率千差萬別。

聯想人做數獨的策略,總是先填可填數最少的那個空,再填選擇第二少的。。。其實這種策略就造就了乙個深度淺時分支也較少的搜尋樹。合適的搜尋順序再配合剪枝==ac。

所以搜尋順序為:從當前可填數的數目最少的那個空開始。注意:每填乙個空,都會導致同行同列同九宮格的空的可填數數目減一,所以不能一開始就排序。(實測這樣做會比正解慢8倍左右,真是恐怖如斯)所以要在分支選擇時去找。為了平衡準確性與高效性,可以用乙個簡單的判斷找到乙個比較合適的空去填(因為如果每次都精確去找那個可填數數目最小的那個空會導致複雜度偏高,因此只要簡單地找到可填數數目相對小的那個空就行)。

找一下搜尋面臨或有關的狀態與維度:當前分數v,當前要填的點的座標,填了t個點,總共要填cnt個點,各行各列各九宮格填數情況。

可行性剪枝考慮:

發現乙個有趣的性質:數獨中每一行都會有1到9各出現一次,共有9行,所以1到9每個數到最後必定出現9次,所以可以設乙個used陣列記錄數出現的次數,若小於0,肯定不是正解,回溯,故每次填空要用不僅usedi大於0且i在同行同列同九宮格都沒有出現過的i。

最優性剪枝:

可以將所有空能填的最大的數*該空的分數求和得到乙個還能得到的至多的分數zhiduo,填空時,若發現v+zhiduo還<=已搜到的答案ans,顯然不會使答案更優,所以回溯;同時每填乙個空都更新一下zhiduo,回溯時也要照顧到zhiduo。

ac**:

1 #include2 #include3 #include4 #include5

6using

namespace

std;78

int a[9][9],fen[9][9],cnt,zhiduo,m[100][2],ans;//

第二下標: 0:縱座標;1:橫座標 先縱再橫

9int ma[10][10],used[10

];10

int h[10],l[10],maxh,maxl;//

某行、列已經填了幾個數

1112

bool hang[10][10],lie[10][10],jiu[3][3][10];//

行、列、九宮格的填數情況

1314

void

init()

1522}23

24void dfs(int k,int v,int x,int y)//

要填第k個,當前分數v,當前填的空的縱、橫座標。

2549

else

50 ans=max(ans,v);

51 v-=fen[x][y]*i; 52}

53}54}

5556

intmain()57

74 hang[i][a[i][j]]=1

;75 lie[j][a[i][j]]=1

;76 jiu[i/3][j/3][a[i][j]]=1

;77 v+=fen[i][j]*a[i][j];78}

79else

80 cnt++;81}

82int

most;

83for(int i=0;i<=8;i++)//

求起始時的至多zhiduo

84for(int j=0;j<=8;j++)

85if(!a[i][j])

8692 h[9]=-165123

;93 l[9]=-151562

;94 maxh=9,maxl=9;95

for(int i=0;i<=8;i++)//

找一開始要填的空

96if(h[i]!=9&&h[i]>h[maxh]) maxh=i;

97for(int i=0;i<=8;i++)

98if(!a[maxh][i]&&l[i]!=9&&l[i]>l[maxl]) maxl=i;

99 dfs(1

,v,maxh,maxl);

100if(!ans) ans=-1

;101 cout<

102return0;

103 }

洛谷1074 靶狀數獨dfs 排序 記錄 搜尋

題目 大意就是在乙個9 9的數獨中填數,要求行列宮都是九個互不相同的數字,給定一定的得分機制,要求求解最大得分。思路大致從零最少的行開始搜尋 試想現實中你做數獨一定是這樣的方法 然後只要將0位置的資訊儲存,總數就是深度值。按照優先搜尋的順序逐個填寫,為了節省計算資源,在搜尋之前就預處理0位置的相關資...

一本通1361 產生數 Produce

1361 產生數 produce 題目描述 給出乙個整數n n 2000 和k個變換規則 k 15 規則 1個數字可以變換成另1個數字 規則中,右邊的數字不能為零。例如 n 234,k 2規則為 2 5 3 6 上面的整數234經過變換後可能產生出的整數為 包括原數 234,534,264,564共...

一本通1536數星星 Stars

時間限制 256 ms 記憶體限制 65536 kb 原題來自 ural 1028 天空中有一些星星,這些星星都在不同的位置,每個星星有個座標。如果乙個星星的左下方 包含正左和正下 有 k k顆星星,就說這顆星星是 k k 級的。例如,上圖中星星 5 5是 3 3級的 1,2 4 1,2,4在它左下...