#10025 「一本通 1.3 练习 4」靶形数独P1074 [NOIP2009 提高组]
[NOIP2009 提高組] 靶形數獨
題目背景
此為遠古題,不保證存在可以通過任意符合要求的輸入數據的程序。
題目描述
小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨游戲,好勝的他們想用數獨來一比高低。但普通的數獨對他們來說都過于簡單了,于是他們向 Z 博士請教,Z 博士拿出了他最近發明的“靶形數獨”,作為這兩個孩子比試的題目。
靶形數獨的方格同普通數獨一樣,在 9 9 9 格寬且 9 9 9 格高的大九宮格中有 9 9 9 個 3 3 3 格寬且 3 3 3 格高的小九宮格(用粗黑色線隔開的)。在這個大九宮格中,有一些數字是已知的,根據這些數字,利用邏輯推理,在其他的空格上填入 1 1 1 到 9 9 9 的數字。每個數字在每個小九宮格內不能重復出現,每個數字在每行、每列也不能重復出現。但靶形數獨有一點和普通數獨不同,即每一個方格都有一個分值,而且如同一個靶子一樣,離中心越近則分值越高。(如圖)
上圖具體的分值分布是:最里面一格(黃色區域)為 10 10 10 分,黃色區域外面的一圈(紅色區域)每個格子為 9 9 9 分,再外面一圈(藍色區域)每個格子為 8 8 8 分,藍色區域外面一圈(棕色區域)每個格子為 7 7 7 分,最外面一圈(白色區域)每個格子為 6 6 6 分,如上圖所示。比賽的要求是:每個人必須完成一個給定的數獨(每個給定數獨可能有不同的填法),而且要爭取更高的總分數。而這個總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字的乘積的總和
總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字的乘積的總和。如圖,在以下的這個已經填完數字的靶形數獨游戲中,總分數為 2829。游戲規定,將以總分數的高低決出勝負。
由于求勝心切,小城找到了善于編程的你,讓你幫他求出,對于給定的靶形數獨,能夠得到的最高分數。
輸入格式
一共 9 9 9 行。每行 9 9 9 個整數(每個數都在 0 ~ 9 0 \sim 9 0~9 的范圍內),表示一個尚未填滿的數獨方格,未填的空格用“ 0 0 0”表示。每兩個數字之間用一個空格隔開。
輸出格式
輸出共 1 1 1 行。輸出可以得到的靶形數獨的最高分數。如果這個數獨無解,則輸出整數 ? 1 -1 ?1。
樣例 #1
樣例輸入 #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
樣例輸入 #2
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樣例輸出 #2
2852提示
數據規模與約定
- 對于 40 % 40\% 40% 的數據,數獨中非 0 0 0 數的個數不少于 30 30 30;
- 對于 80 % 80\% 80% 的數據,數獨中非 0 0 0 數的個數不少于 26 26 26;
- 對于 100 % 100\% 100% 的數據,數獨中非 0 0 0 數的個數不少于 24 24 24。
我真的太喜歡大法師啦()
#TLE就是大法師的贊歌!!!!!!
大致思路
根據題意,我們需要判斷橫向,縱向及一個3x3矩形內是否有重復元素,因此,我們可以開三個二維數組對其進行儲存。用近似打表(?)的方式存儲權值。
int x[15][15],y[15][15],xy[15][15],va[12][12]={ {0,0,0,0,0,0,0,0,0,0,0,0,}, {0,6,6,6,6,6,6,6,6,6,}, {0,6,7,7,7,7,7,7,7,6,}, {0,6,7,8,8,8,8,8,7,6,}, {0,6,7,8,9,9,9,8,7,6,}, {0,6,7,8,9,10,9,8,7,6,}, {0,6,7,8,9,9,9,8,7,6,}, {0,6,7,8,8,8,8,8,7,6,}, {0,6,7,7,7,7,7,7,7,6,}, {0,6,6,6,6,6,6,6,6,6,}, },a[12][12];9x9的矩形中有9個3x3的小矩形,我們可以用函數來完成當前坐標屬于那個矩形的判斷
int sl(int x,int y){if(x<=3){if(y<=3)return 1;if(y<=6)return 2;if(y<=9)return 3;}if(x<=6){if(y<=3)return 4;if(y<=6)return 5;if(y<=9)return 6;}if(x<=9){if(y<=3)return 7;if(y<=6)return 8;if(y<=9)return 9;} }dfs部分
顯而易見,我們的數獨排列從一行中已經有數的開始搜索可以更好地縮小搜索樹,我們可以對搜索順序進行規劃。
bool cmp(int a,int b){return num[a]>num[b]; } for(int i=1;i<=9;i++){sortxu[i]=i;for(int j=1;j<=9;j++){cin>>a[i][j];if(a[i][j]){x[i][a[i][j]]=y[a[i][j]][j]=xy[sl(i,j)][a[i][j]]=1;num[i]++;}}}sort(sortxu+1,sortxu+10,cmp);剩下的基本就只需套dfs模板啦。
void dfs(int xx,int yy,int sum,int xu){if(yy==10){//換行if(xu==9){//搜索完畢ans=max(sum,ans);return;}dfs(sortxu[xu+1],1,sum,xu+1);//下一行搜索return;}if(xx>=10||yy>=10)return;//邊界int ju=sl(xx,yy);//判斷當前屬于那個3x3小矩形if(a[xx][yy]){dfs(xx,yy+1,sum+a[xx][yy]*va[xx][yy],xu);}//當前位置之前已經有數else //沒數,枚舉for(int l=1;l<=9;l++){if(x[xx][l]==0&&y[l][yy]==0&&xy[ju][l]==0){x[xx][l]=y[l][yy]=xy[ju][l]=1;dfs(xx,yy+1,sum+l*va[xx][yy],xu);x[xx][l]=y[l][yy]=xy[ju][l]=0;//回溯}} }斯巴拉西
AC CODE
#include<bits/stdc++.h> using namespace std; int num[10],sortxu[10],ans=-1; int x[15][15],y[15][15],xy[15][15],va[12][12]={ {0,0,0,0,0,0,0,0,0,0,0,0,}, {0,6,6,6,6,6,6,6,6,6,}, {0,6,7,7,7,7,7,7,7,6,}, {0,6,7,8,8,8,8,8,7,6,}, {0,6,7,8,9,9,9,8,7,6,}, {0,6,7,8,9,10,9,8,7,6,}, {0,6,7,8,9,9,9,8,7,6,}, {0,6,7,8,8,8,8,8,7,6,}, {0,6,7,7,7,7,7,7,7,6,}, {0,6,6,6,6,6,6,6,6,6,}, },a[12][12]; int sl(int x,int y){if(x<=3){if(y<=3)return 1;if(y<=6)return 2;if(y<=9)return 3;}if(x<=6){if(y<=3)return 4;if(y<=6)return 5;if(y<=9)return 6;}if(x<=9){if(y<=3)return 7;if(y<=6)return 8;if(y<=9)return 9;} } bool cmp(int a,int b){return num[a]>num[b]; } void dfs(int xx,int yy,int sum,int xu){if(yy==10){//換行if(xu==9){//搜索完畢ans=max(sum,ans);return;}dfs(sortxu[xu+1],1,sum,xu+1);//下一行搜索return;}if(xx>=10||yy>=10)return;//邊界int ju=sl(xx,yy);//判斷當前屬于那個3x3小矩形if(a[xx][yy]){dfs(xx,yy+1,sum+a[xx][yy]*va[xx][yy],xu);}//當前位置之前已經有數else //沒數,枚舉for(int l=1;l<=9;l++){if(x[xx][l]==0&&y[l][yy]==0&&xy[ju][l]==0){x[xx][l]=y[l][yy]=xy[ju][l]=1;dfs(xx,yy+1,sum+l*va[xx][yy],xu);x[xx][l]=y[l][yy]=xy[ju][l]=0;//回溯}} } int main(){for(int i=1;i<=9;i++){sortxu[i]=i;for(int j=1;j<=9;j++){cin>>a[i][j];if(a[i][j]){x[i][a[i][j]]=y[a[i][j]][j]=xy[sl(i,j)][a[i][j]]=1;num[i]++;}}}sort(sortxu+1,sortxu+10,cmp);dfs(sortxu[1],1,0,1);cout<<ans;return 0; }總結
以上是生活随笔為你收集整理的#10025 「一本通 1.3 练习 4」靶形数独P1074 [NOIP2009 提高组]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电机控制基本原理
- 下一篇: 第13期 《不一样的选择,不一样的世界》