[NOIP2009] 靶形數獨(搜索+剪枝)

来源:http://www.cnblogs.com/zoewilly/archive/2016/10/31/6017202.html
-Advertisement-
Play Games

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


題目描述

小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨游戲,好勝的他

們想用數獨來一比高低。但普通的數獨對他們來說都過於簡單了,於是他們向 Z 博士請教,

Z 博士拿出了他最近發明的“靶形數獨”,作為這兩個孩子比試的題目。

靶形數獨的方格同普通數獨一樣,在 9 格寬×9 格高的大九宮格中有 9 個 3 格寬×3 格

高的小九宮格(用粗黑色線隔開的)。在這個大九宮格中,有一些數字是已知的,根據這些數字,利用邏輯推理,在其他的空格上填入 1 到 9 的數字。每個數字在每個小九宮格內不能

重覆出現,每個數字在每行、每列也不能重覆出現。但靶形數獨有一點和普通數獨不同,即

每一個方格都有一個分值,而且如同一個靶子一樣,離中心越近則分值越高。(如圖)

上圖具體的分值分佈是:最裡面一格(黃色區域)為 10 分,黃色區域外面的一圈(紅

色區域)每個格子為 9 分,再外面一圈(藍色區域)每個格子為 8 分,藍色區域外面一圈(棕

色區域)每個格子為 7 分,最外面一圈(白色區域)每個格子為 6 分,如上圖所示。比賽的

要求是:每個人必須完成一個給定的數獨(每個給定數獨可能有不同的填法),而且要爭取

更高的總分數。而這個總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字

的乘積的總和

總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字

的乘積的總和。如圖,在以下的這個已經填完數字的靶形數獨游戲中,總分數為 2829。游戲規定,將以總分數的高低決出勝負。

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

夠得到的最高分數。

輸入輸出格式

輸入格式:

一共 9 行。每行 9 個整數(每個數都在 0―9 的範圍內),表示一個尚未填滿的數獨方

格,未填的空格用“0”表示。每兩個數字之間用一個空格隔開。

輸出格式:

輸出文件 sudoku.out 共 1 行。

輸出可以得到的靶形數獨的最高分數。如果這個數獨無解,則輸出整數-1。

輸入輸出樣例

輸入樣例#1:
sudoku1
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

sudoku2
0 0 0 7 0 2 4 5 3 
9 0 0 0 0 8 0 0 0 
7 4 0 0 0 5 0 1 0 
1 9 5 0 8 0 0 0 0 
0 7 0 0 0 0 0 2 5 
0 3 0 5 7 9 1 0 8 
0 0 0 6 0 1 0 0 0 
0 6 0 9 0 0 0 0 1 
0 0 0 0 0 0 0 0 6
輸出樣例#1:
sudoku1
2829

sudoku2
2852

說明

【數據範圍】

40%的數據,數獨中非 0 數的個數不少於 30。

80%的數據,數獨中非 0 數的個數不少於 26。

100%的數據,數獨中非 0 數的個數不少於 24。

NOIP 2009 提高組 第四題

 

  • 看完題目,貌似沒有什麼更好的解決方法,那就搜索了。
  • 但是通過觀察數據範圍,如果沒有什麼好的搜索策略,複雜度大概為O(sum^9),這不是個理想的策略。
  • 簡單易想的剪枝策略:一邊搜一邊判斷,大概能優化很多,期望得分60分。
  • 通過題意可以得出一個較好的搜索策略:根據每行每列需要搜索的數字個數(即開始數獨前未給出數字的格子的個數)統計出來,根據個數從小到大排序,得出一個較好的行列搜索順序。
  • 然後就搜吧!
  • 期望得分100分。

 

 

  1 #include <cstdio>
  2 #include <algorithm>
  3 using namespace std;
  4 
  5 struct ha{
  6     int m,cnt;
  7 } a[15];
  8 
  9 struct li{
 10     int m,cnt;
 11 } b[15];
 12 
 13 bool cmp1(const ha x,const ha y) {
 14     return (x.cnt>y.cnt);
 15 }
 16 
 17 bool cmp2(const li x,const li y) {
 18     return x.cnt>y.cnt;
 19 }
 20 
 21 const int w[10][10]=
 22     {0,0,0,0,0,0,0,0,0,0,
 23     0,6,6,6,6,6,6,6,6,6,
 24     0,6,7,7,7,7,7,7,7,6,
 25     0,6,7,8,8,8,8,8,7,6,
 26     0,6,7,8,9,9,9,8,7,6,
 27     0,6,7,8,9,10,9,8,7,6,
 28     0,6,7,8,9,9,9,8,7,6,
 29     0,6,7,8,8,8,8,8,7,6,
 30     0,6,7,7,7,7,7,7,7,6,
 31     0,6,6,6,6,6,6,6,6,6};
 32     
 33 const int num[10][10]=
 34     {0,0,0,0,0,0,0,0,0,0,
 35     0,1,1,1,2,2,2,3,3,3,
 36     0,1,1,1,2,2,2,3,3,3,
 37     0,1,1,1,2,2,2,3,3,3,
 38     0,4,4,4,5,5,5,6,6,6,
 39     0,4,4,4,5,5,5,6,6,6,
 40     0,4,4,4,5,5,5,6,6,6,
 41     0,7,7,7,8,8,8,9,9,9,
 42     0,7,7,7,8,8,8,9,9,9,
 43     0,7,7,7,8,8,8,9,9,9};
 44     
 45 int n=9,x,tot,kashi,ans=-1,sum=0,map[15][15],quex[15],quey[15];
 46 bool f[15][15],hang[15][15],lie[15][15],ge[15][15],wujie,ka;
 47 
 48 void dfs(int u,int v) {
 49     if (u>n) {
 50         ans=max(ans,sum);
 51         return;        
 52     }
 53     int x=a[u].m;
 54     int y=b[v].m;
 55     if (f[x][y]) {
 56         if (v<n) dfs(u,v+1); else dfs(u+1,1);
 57         return;
 58     }
 59     for (int i=1; i<=9; i++) {
 60         if (hang[x][i]) continue;
 61         if (lie[y][i]) continue;
 62         if (ge[num[x][y]][i]) continue;
 63         hang[x][i]=1;
 64         lie[y][i]=1;
 65         ge[num[x][y]][i]=1;
 66         sum+=w[x][y]*i;
 67         if (v<n) dfs(u,v+1); else dfs(u+1,1);
 68         hang[x][i]=0;
 69         lie[y][i]=0;
 70         ge[num[x][y]][i]=0;
 71         sum-=w[x][y]*i;
 72     }
 73 }    
 74     
 75 int main() {
 76     for (int i=1; i<=n; i++) {
 77         for (int j=1; j<=n; j++) {
 78             scanf("%d",&x);
 79             if (x) {
 80                 a[i].cnt++;
 81                 b[j].cnt++;
 82                 hang[i][x]=1;
 83                 lie[j][x]=1;
 84                 ge[num[i][j]][x]=1;
 85                 sum+=w[i][j]*x;
 86                 f[i][j]=1;
 87             }
 88         }
 89     }
 90     for (int i=1; i<=n; i++) {
 91         a[i].m=i;
 92         b[i].m=i;
 93     }
 94     sort(a+1,a+n+1,cmp1);
 95     sort(b+1,b+n+1,cmp2);
 96     //for (int i=1; i<=n; i++) printf("%d ",a[i].m);
 97     //for (int i=1; i<=n; i++) printf("%d ",b[i].m);
 98     dfs(1,1);
 99     printf("%d",ans);
100     return 0;
101 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今日問題: 請問主程式輸出結果是?(點擊以下“【Java每日一題】20161101”查看20161031問題解析) 題目原發佈於公眾號、簡書:【Java每日一題】20161101,【Java每日一題】20161101 每日一題最新將在公眾號發佈,歡迎訂閱,交流進步 ...
  • 下麵是 Java 線程相關的熱門面試題,你可以用它來好好準備面試。 1) 什麼是線程? 線程是操作系統能夠進行運算調度的最小單位,它被包含在進程之中,是進程中的實際運作單位。程式員可以通過它進行多處理器編程,你可以使用多線程對運算密集型任務提速。比如,如果一個線程完成一個任務要 100 毫秒,那麼用 ...
  • 如今的互聯網,採集網站非常多,很多網站都喜歡盜鏈/盜用別人網站的圖片,這樣不僅侵犯網權,還導致被盜鏈的網站消耗大量的流量,給伺服器造成比較大的壓力,本文章向大家介紹php如何防止圖片盜用/盜鏈的兩種方法,需要的朋友可以參考一下。 圖片防盜鏈有什麼用? 防止其它網站盜用你的圖片,浪費你寶貴的流量。本文 ...
  • 這次主要是講解一下通過登錄後對得到的數據進行分頁,首先我們新建一個登錄頁面login.jsp,因為我們主要學習一下分頁,所以登錄驗證的部分不再闡述,主要代碼如下: 首先建立實體類User.java並添加get和set方法: 我們可以看到form表單是提交到pageServlet中,所以我們新建一個P ...
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://user-20160821pd:8088/com.jdbc2/"> <title>My JSP 'inde ...
  • 搜索功能 DAO層都是一些資料庫的增刪改查操作 Servlet,控制層 點擊頁面的搜索,把輸入的信息提交到servlet, 實體Bean是針對資料庫中的欄位而建的, 不和資料庫做對應,而是打包一些零散的值的Bean,和它的頁面做對應,包名為:com.xxx.view 針對頁面的實體Bean 頁面亂碼 ...
  • Java的序列化流程如下: Java的反序列化流程如下: 註意:並不是所有類都需要進行序列化,主要原因有兩個 1)安全問題。Java中有的類屬於敏感類,此類的對象數據不便對外公開,而序列化的對象數據很容易進行破解,無法保證其數據的安全性,因此一般這種類型的對象不會進行序列化。 2)資源問題。可以使用 ...
  • 總結一下內置函數,Build-in Function。 一、數學運算類 求絕對值 二、集合類操作 三、邏輯判斷 四、反射 五、IO操作 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...