您的位置:首页 > 其它

[NOIP2009]靶形数独

2014-10-17 21:17 771 查看
传说中的神级搜索题……

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

1 #include <algorithm>
2 #include <cstdio>
3 #include <cctype>
4 #include <cmath>
5 #include <vector>
6 #include <queue>
7
8 #define maxn ((int)1e5 + 4)
9 #if defined DEBUG
FILE *in = fopen("test", "r");
#define out stdout
#else
FILE *in = fopen("sudoku.in", "r");
FILE *out = fopen("sudoku.out", "w");
#endif
using namespace std;
inline void getint(int &x){
char c = fgetc(in);
while(!isdigit(c)) c = fgetc(in);
x = c - '0';
while(isdigit(c = fgetc(in)))x = x * 10 - '0' + c;
}

/*===========================================*/
#define lowbit(x) (x & -x)
#define gs(x, y) (x / 3 * 3 + y / 3)
#define f(a) (bitcnt(RNG &~(row[a.x] | col[a.y] | squ[gs(a.x,a.y)])))
const int RNG = 1022/*状态的范围*/,val[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}};
struct P{
int x, y;
P(){}
}blank[80];
int bcnt = 0, ord[80];
int row[9] = {0}, col[9] = {0}, squ[9] = {0};//状态
int ans = 0;
bool known = 0;
inline int bitcnt(int x){
int a = 0;
while(x){
if(x & 1)++a;
x >>= 1;
}
return a;
}
inline void init(){
int i, j, k, t;
for(i = 0;i < 9;++i)for(j = 0;j < 9;++j){
getint(k);
if(k){
t = 1 << k;
row[i] ^= t, col[j] ^= t, squ[gs(i,j)] ^= t;
ans += k * val[i][j];
}
else{
ord[bcnt] = bcnt;
blank[bcnt].x = i;
blank[bcnt++].y = j;
}
}
}
inline void dfs(int cur, int now){
if(cur == bcnt){
if(now > ans)ans = now,known = 1;
return;
}
int mincnt = 10, min_it, i, t;
for(i = cur;i < bcnt;++i)
if((t = f(blank[ord[i]])) < mincnt)
mincnt = t, min_it = i;
P x = blank[ord[min_it]];
if(cur!=min_it)ord[cur] ^= ord[min_it] ^= ord[cur] ^= ord[min_it];
int bits = RNG &~(row[x.x] | col[x.y] | squ[gs(x.x,x.y)]);
while(bits){
t = lowbit(bits); bits ^= t;
i = bitcnt(t - 1);
row[x.x] ^= t, col[x.y] ^= t, squ[gs(x.x,x.y)] ^= t;
dfs(cur + 1, now + i * val[x.x][x.y]);
row[x.x] ^= t, col[x.y] ^= t, squ[gs(x.x,x.y)] ^= t;
}
}
int main(){
init();
dfs(0, ans);
if(known)
fprintf(out, "%d\n", ans);
else fprintf(out, "-1\n");
return 0;
}状态压缩+启发式搜索
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: