您的位置:首页 > 其它

[COGS 0407][NOIP 2009] 靶形数独

2017-08-08 18:49 375 查看

407. [NOIP2009] 靶形数独

★★ 输入文件:
sudoku.in
输出文件:
sudoku.out
简单对比
时间限制:5 s 内存限制:128 MB

【问题描述】

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目。
靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的) 。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1到 9 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。 (如图)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
typedef std::pair<int,int> Point;

const int MAXN=20;

const int score[MAXN][MAXN]={{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}};
const int block[MAXN][MAXN]={{0},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9}};

int ans=-1;
int known;
int unknown;
Point u[MAXN*MAXN];
bool col[MAXN][MAXN];
bool row[MAXN][MAXN];
bool visited[MAXN][MAXN];

void Initialize();
void DFS(int,int);

int main(){
Initialize();
DFS(unknown,known);
printf("%d\n",ans);
return 0;
}

void DFS(int rest,int sum){
if(rest==0){
ans=std::max(ans,sum);
return;
}
else{
for(int i=1;i<=9;i++){
if(!visited[block[u[rest].first][u[rest].second]][i]&&!row[u[rest].first][i]&&!col[u[rest].second][i]){
row[u[rest].first][i]=true;
col[u[rest].second][i]=true;
visited[block[u[rest].first][u[rest].second]][i]=true;
DFS(rest-1,sum+score[u[rest].first][u[rest].second]*i);
visited[block[u[rest].first][u[rest].second]][i]=false;
col[u[rest].second][i]=false;
row[u[rest].first][i]=false;
}
}
}
}

void Initialize(){
#ifndef ASC_LOCAL
freopen("sudoku.in","r",stdin);
freopen("sudoku.out","w",stdout);
#endif
int tmp;
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
scanf("%d",&tmp);
if(tmp==0){
unknown++;
u[unknown].first=i;
u[unknown].second=j;
}
else{
known+=tmp*score[i][j];
visited[block[i][j]][tmp]=true;
row[i][tmp]=true;
col[j][tmp]=true;
}
}
}
}


Backup
日常图包w
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: