靶形數獨 (codevs 1174)題解

2021-07-09 09:34:38 字數 4177 閱讀 3324

【問題描述】

小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他們想用數獨來一比高低。但普通的數獨對他們來說都過於簡單了,於是他們向z 博士請教,z 博士拿出了他最近發明的「靶形數獨」,作為這兩個孩子比試的題目。靶形數獨的方格同普通數獨一樣,在 9 格寬×9 格高的大九宮格中有9 個3 格寬×3 格高的小九宮格(用粗黑色線隔開的)。在這個大九宮格中,有一些數字是已知的,根據這些數字,利用邏輯推理,在其他的空格上填入1 到9 的數字。每個數字在每個小九宮格內不能重複出現,每個數字在每行、每列也不能重複出現。但靶形數獨有一點和普通數獨不同,即每乙個方格都有乙個分值,而且如同乙個靶子一樣,離中心越近則分值越高。

下圖具體的分值分布是:最裡面一格(黃色區域)為 10 分,黃色區域外面的一圈(紅色區域)每個格仔為9 分,再外面一圈(藍色區域)每個格仔為8 分,藍色區域外面一圈(棕色區域)每個格仔為7 分,最外面一圈(白色區域)每個格仔為6 分,如上圖所示。比賽的要求是:每個人必須完成乙個給定的數獨(每個給定數獨可能有不同的填法),而且要爭取更高的總分數。而這個總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字的乘積的總和。如圖,在以下的這個已經填完數字的靶形數獨遊戲中,總分數為2829。遊戲規定,將以總分數的高低決出勝負。

由於求勝心切,小城找到了善於程式設計的你,讓你幫他求出,對於給定的靶形數獨,能夠得到的最高分數。

7 0 0 9 0 0 0 0 1

1 0 0 0 0 5 9 0 0

0 0 0 2 0 0 0 8 0

0 0 5 0 2 0 0 0 3

0 0 0 0 0 0 6 4 8

4 1 3 0 0 0 0 0 0

0 0 7 0 0 2 0 9 0

2 0 1 0 6 0 8 0 4

0 8 0 5 0 4 0 1 2

2829

2852

本題為noip2009提高組第四題,時間給的很充裕,4s的時間深搜綽綽有餘(真不知道為什麼題解中說要卡評測機……),只需稍作優化即可,然後注意一下數獨的規則,注意如何判重。

下面來說說優化。

首先記錄下0的個數和位置,然後只需要對每個0的位置從1搜尋到9即可,題目中說非0的個數不少於24,這樣下來時間複雜度就減少了o((24*9)^n),然後……似乎就沒有然後了。

1

type rec=record

2x,y:longint;

3end;4

const fs:array[1..9,1..9] of longint=((6,6,6,6,6,6,6,6,6

),5 (6,7,7,7,7,7,7,7,6

),6 (6,7,8,8,8,8,8,7,6

),7 (6,7,8,9,9,9,8,7,6

),8 (6,7,8,9,10,9,8,7,6

),9 (6,7,8,9,9,9,8,7,6

),10 (6,7,8,8,8,8,8,7,6

),11 (6,7,7,7,7,7,7,7,6

),12 (6,6,6,6,6,6,6,6,6

));13 num:array[1..9,1..9] of longint=((1,1,1,2,2,2,3,3,3

),14 (1,1,1,2,2,2,3,3,3

),15 (1,1,1,2,2,2,3,3,3

),16 (4,4,4,5,5,5,6,6,6

),17 (4,4,4,5,5,5,6,6,6

),18 (4,4,4,5,5,5,6,6,6

),19 (7,7,7,8,8,8,9,9,9

),20 (7,7,7,8,8,8,9,9,9

),21 (7,7,7,8,8,8,9,9,9

));22

var c:array[1..9,1..9] of

longint;

23i,j,ans,n,w,max:longint;

24 a:array[1..60] of

rec;

25 f1,f2,f3:array[1..9,1..9] of

boolean;

26procedure

dfs(n:longint);

27var

i,j,k:longint;

28begin

29if n=0

then

30begin

31if ans>max then

32 max:=ans;

33exit;

34end

;35 i:=a[n].x;

36 j:=a[n].y;

37for k:=1to9

do38

if (f1[i,k])and(f2[j,k])and(f3[num[i,j],k]) then

39begin

40 f1[i,k]:=false;

41 f2[j,k]:=false;

42 f3[num[i,j],k]:=false;

43 c[i,j]:=k;

44 ans:=ans+k*fs[i,j];

45 dfs(n-1

);46 ans:=ans-k*fs[i,j];

47 f1[i,k]:=true;

48 f2[j,k]:=true;

49 f3[num[i,j],k]:=true;

50end;51

end;

52begin

53fillchar(f1,sizeof(f1),true);

54fillchar(f2,sizeof(f2),true);

55fillchar(f3,sizeof(f3),true);

56for i:=1to9

do57

for j:=1to9

do58

begin

59read(c[i,j]);

60if c[i,j]=0

then

61begin

62inc(n);

63 a[n].x:=i;

64 a[n].y:=j;

65end

66else

67begin

68 f1[i,c[i,j]]:=false;

69 f2[j,c[i,j]]:=false;

70 f3[num[i,j],c[i,j]]:=false;

71 ans:=ans+c[i,j]*fs[i,j];

72end;73

end;

74dfs(n);

75for i:=1to9

do76

for j:=1to9

do77

if c[i,j]=0

then

78begin

79 writeln(-1

);80

halt;

81end;82

writeln(max);

83end.

codevs1174 靶形數獨

題目鏈結 題解 可以預處理出已經填數字比較密集的區域開始搜尋來減少後續決策數 include include include using namespace std const int n 9 int s,tot,ans int a 10 10 struct dataf 10 10 int fen ...

靶形數獨(codevs 1174)

2009年noip全國聯賽提高組 時間限制 4 s 空間限制 128000 kb 題目等級 鑽石 diamond 題解檢視執行結果 小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他 們想用數獨來一比高低。但普通的數獨對他們來說都過於簡單了,於是他們向z 博士請教,z 博士...

codevs1174 靶形數獨

從wyh大佬那裡蹭來了乙份dlx的題解,然後進行了一番深刻的理解,最後自己手打了一遍,感覺受益頗多,最主要的是這個 融合了很多卡常技巧2333333333 和普通的dfs不同,這份 從根進行剪枝,每一層都取方案數最小的位置進行搜尋,因而得到十分顯著的優化,原來乙個點4s的題,現在20個點總共用時加起...