您的位置:首页 > 其它

Vijos1775 CodeVS1174 NOIP2009 靶形数独

2017-08-14 09:46 239 查看

靶形数独

描述

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他

们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,

Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目。

靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格

高的小九宫格(用粗黑色线隔开的) 。在这个大九宫格中,有一些数字是已知的,根据这些

数字,利用逻辑推理,在其他的空格上填入 1到 9 的数字。每个数字在每个小九宫格内不能

重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即

每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。 (如图)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#define max(a, b) ((a) > (b) ? (a) : (b))

const int point[9][9] = {{6,6,6,6,6,6,6,6,6},
{6,7,7,7,7,7,7,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,9,10,9,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,7,7,7,7,7,7,6},
{6,6,6,6,6,6,6,6,6}};
const int yu[10][10] = {{0,0,0,0,0,0,0,0,0,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}};

inline void read(int &x)
{
x = 0;char ch = getchar(), c = ch;
while(ch < '0' || ch > '9')c = ch, ch = getchar();
while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
if(c == '-')x = -x;
}

struct Node
{
int x, y;
Node(int _x, int _y){x = _x;y = _y;}
Node(){};
}tian[85];

int num[10][10],ge[10][10],col[10][10],row[10][10],cnt,ans,sum;
int ok[10][10][10];//存每个方格可以填的数

bool cmp(Node a, Node b)
{
return a.x == b.x ? a.y > b.y :a.x > b.x;
}

void dfs(int now)
{
if((cnt - now + 1) * 90 + sum <= ans)return;
if(now == cnt + 1)
{
ans = max(ans, sum);
return;
}
register int x = tian[now].x, y = tian[now].y;
for(register int i = ok[x][y][0];i >= 1;-- i)
{
int shu = ok[x][y][i];
if(num[x][y] || row[x][shu] || col[y][shu] || ge[yu[x][y]][shu])continue;
row[x][shu] = col[y][shu] = ge[yu[x][y]][shu] = 1;num[x][y] = shu,sum += shu * point[x - 1][y - 1];
dfs(now + 1);
sum -= shu * point[x - 1][y - 1],row[x][shu] = col[y][shu] = ge[yu[x][y]][shu] = num[x][y] = 0;
}
return;
}

int main()
{
for(register int i = 1;i <= 9;++ i)for(register int j = 1;j <= 9;++ j)
{
read(num[i][j]);
if(num[i][j])
ge[yu[i][j]][num[i][j]] = row[i][num[i][j]] = col[j][num[i][j]] = 1, sum += num[i][j] * point[i - 1][j - 1];
}
for(register int i = 1;i <= 9;++ i)for(register int j = 1;j <= 9;++ j)
if(!num[i][j])
{
for(register int k = 1;k <= 9;++ k)
if(!col[j][k] && !row[i][k] && !ge[yu[i][j]][k])
ok[i][j][++ok[i][j][0]] = k;
tian[++cnt] = Node(i,j);
}
std::sort(tian + 1, tian + 1 + cnt, cmp);
ans = -1;
dfs(1);
printf("%d", ans);
return 0;
}


View Co靶形数独
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: