靶形數獨 (codevs 1174)題解

【問題描述】

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

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

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

【樣例輸入1】

    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

【樣例輸出1】

    2829

【樣例輸入2】

    2852

【解題思路】

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

      下面來說說優化。

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

【代碼實現】

 1 type rec=record
 2      x,y:longint;
 3 end;
 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;
23     i,j,ans,n,w,max:longint;
24     a:array[1..60] of rec;
25     f1,f2,f3:array[1..9,1..9] of boolean;
26 procedure dfs(n:longint);
27 var i,j,k:longint;
28 begin
29  if n=0 then
30   begin
31    if ans>max then
32     max:=ans;
33    exit;
34   end;
35  i:=a[n].x;
36  j:=a[n].y;
37  for k:=1 to 9 do
38   if (f1[i,k])and(f2[j,k])and(f3[num[i,j],k])  then
39    begin
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;
50       end;
51 end;
52 begin
53  fillchar(f1,sizeof(f1),true);
54  fillchar(f2,sizeof(f2),true);
55  fillchar(f3,sizeof(f3),true);
56  for i:=1 to 9 do
57   for j:=1 to 9 do
58    begin
59     read(c[i,j]);
60     if c[i,j]=0 then
61      begin
62       inc(n);
63       a[n].x:=i;
64       a[n].y:=j;
65      end
66     else
67      begin
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];
72      end;
73    end;
74  dfs(n);
75  for i:=1 to 9 do
76   for j:=1 to 9 do
77    if c[i,j]=0 then
78     begin
79      writeln(-1);
80      halt;
81     end;
82  writeln(max);
83 end.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章