#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define N 9
#define SET_BIT(x,b) x |= ((1 << b)&0xFF)
#define USET_BIT(x,b) x &= ~(1 << b)
#define RD_BIT(x,b) x&(1 << b)
// 测试用例1
char box1[N*N] = ".........963278541254961378547612839192387456386549127675893214421756983839124765";
char box1_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";
// 测试用例2
char box2[N*N] = "...435692...278541...961378547612839192387456386549127675893214421756983839124765";
char box2_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";
char box3[N*N] = ".18435692.63278541.54961378.47612839.92387456.86549127.75893214.21756983.39124765";
char box3_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";
char box4[N*N] = ".18439992963278541254961378547612839192387456386549127675893214421756983839124765";
char box4_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";
char box5[N*N] = "63...12....5.3..71.41..9.36.1.68.9.....14..8.384...1..8.6.1.3.51.93.8..2...5.2.1.";
char box5_out[N*N] = "638471259295836471741259836517683924962147583384925167826714395159368742473592618";
char box6[N*N] = "....3..9....2....1.5.9..............1.2.8.4.6.8.5...2..75......4.1..6..3.....4.6.";
char box6_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";
//char last[N*N];
/* 根据当前坐标,计算出相邻8个格子坐标的差值 */
char near[][8] = {{1, 2, 9, 10, 11, 18, 19, 20}, {-1, 1, 8, 9, 10, 17, 18, 19},
{-2, -1, 7, 8, 9, 16, 17, 18}, {-9, -8, -7, 1, 2, 9, 10, 11},
{-10, -9, -8, -1, 1, 8, 9, 10}, {-11, -10, -9, -2, -1, 7, 8,
9}, {-18, -17, -16, -9, -8, -7, 1, 2},
{-19, -18, -17, -10, -9, -8, -1, 1},
{-20, -19, -18, -11, -10, -9, -2, -1}};
void pp(char a[N])
{
int i, j;
for (j = 0;j < N;++j)
{
for (i = 0;i < N;++i)
{
printf("%c ", a[j*N+i]);
}
printf("/n");
}
printf("/n");
}
int index(x)
{
int i = 0;
x = x % 27;
i = x%3 + x/9*3;
}
int check(char a[], int x)
{
int i, j, k;
int bits = 0xFF;
USET_BIT(bits, a[x] - '0');
// printf("check 1/n"); /* 检查x所属小单元里面是1~9 */
for (i = 0, j = index(x);i < 8;++i)
{
k = x + near[j][i];
if (a[k] == '0'||a[k] == '.') continue;
if (a[k] == a[x])
{
// printf("a[%d] == a[%d]/n", k, x);
return 0;
}
}
// printf("check 2/n"); /* 检查每一行是1~9 */
for (i = x/9*9;i < x/9*9+9;++i)
{
if (i == x)
continue;
if (a[i] == a[x])
{
// printf("a[%d] == a[%d]/n", i, x);
return 0;
}
}
// printf("check 3/n"); /* 检查每一列是1~9 */
for (i = x%9;i < 81;i += 9)
{
if (i == x)
continue;
if (a[x] == a[i])
{
// printf("a[%d] == a[%d]/n", i, x);
return 0;
}
}
return 1;
}
/* 计算出结果返回1, 没有解返回0 */
int compute(char *arr)
{
int i = 0, j = 0;
char last[N*N] = {0}; // 回溯的状态
for (i = 0;i < N*N;++i)
if ('.' != arr[i])
last[i] = '*';
else
last[i] = '0';
i = 0;
while (i >= 0)
{
if ('*' == last[i])
{
++i;
continue;
}
if (i >= 81)
{
for (j = 0;j < 81;++j)
{
if (!check(arr, j))
return 0;
}
return 1;
}
arr[i] = last[i] + 1;
while (arr[i] <= '9')
{
if (!check(arr, i))
{
++arr[i];
}
else
{
if (i == 80)
{
return 1;
// printf("out: =====================================/n");
// pp(arr);
// getchar();
arr[i] = '9' + 1;
}
break;
}
}
if (arr[i] > '9')
{
last[i] = '0';
arr[i] = '0';
--i;
while ('*' == last[i])
{
--i;
}
continue;
}
/* pp(arr); */
/* getchar(); */
last[i] = arr[i];
++i;
}
return 0;
}
int main()
{
int i, j;
/* for (j = 0;j < N;++j) */
/* { */
/* for (i = 0;i < N;++i) */
/* { */
/* scanf("%c", arr[j][i]); */
/* } */
/* } */
/* for (i = 0;i < 81;++i) */
/* { */
/* printf("%d %d/n", i, index(i)); */
/* } */
printf("----------test1---------/n");
pp(box1);
if (compute(box1))
{
assert(strncmp(box1, box1_out, N*N) == 0);
pp(box1);
}
else
printf("NO Answer!/n");
printf("----------test2---------/n");
pp(box2);
if (compute(box2))
{
assert(strncmp(box2, box2_out, N*N) == 0);
pp(box2);
}
else
printf("NO Answer!/n");
printf("----------test3---------/n");
pp(box3);
if (compute(box3))
{
assert(strncmp(box3, box3_out, N*N) == 0);
pp(box3);
}
else
printf("NO Answer!/n");
printf("----------test4---------/n");
pp(box4);
if (compute(box4))
{
assert(strncmp(box4, box4_out, N*N) == 0);
pp(box4);
}
else
printf("NO Answer!/n");
printf("----------test5---------/n");
pp(box5);
if (compute(box5))
{
assert(strncmp(box5, box5_out, N*N) == 0);
pp(box5);
}
else
printf("NO Answer!/n");
printf("----------test6---------/n");
pp(box6);
if (compute(box6))
{
assert(strncmp(box6, box6_out, N*N) == 0);
pp(box6);
}
else
printf("NO Answer!/n");
return 1;
}