MM中午给了我个数独……俺作了半个小时,眼看时间就要上班了,实在是做不出来了:'(但是自称数独高手的我不能在她面前丢人,思前想后,还是写个程序来吧,节省点时间~
大概花了我一个半小时,解决问题……下班后又稍微整理了一下,改成读文件了,但愿对后来人有帮助,不用像我这么狼狈,从头写了:)
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#define LEN 9
#define SP 3
int g_times = 0;
void init(char data[LEN][LEN], char store[LEN][LEN][LEN])
{
for(int i = 0; i < LEN; i++)
for(int j = 0; j < LEN; j++)
if(data[i][j])
{
memset(store[i][j], 0, LEN);
store[i][j][data[i][j] - 1] = 1;
}
}
void upstore(char data[LEN][LEN], char store[LEN][LEN][LEN])
{
for(int i = 0; i < LEN; i++)
{
for(int j = 0; j < LEN; j++)
{
if(data[i][j] == 0)
continue;
/* reset h-line */
for(int k = 0; k < LEN; k++)
store[i][k][data[i][j] - 1] = 0;
/* reset v-line */
for(int k = 0; k < LEN; k++)
store[k][j][data[i][j] - 1] = 0;
/* reset group */
for(int k = 0; k < SP; k++)
for(int m = 0; m < SP; m++)
store[i / SP * SP + m][j / SP * SP + k][data[i][j] - 1] = 0;
store[i][j][data[i][j] - 1] = 1;
}
}
}
int evolution(char data[LEN][LEN])
{
char store[LEN][LEN][LEN];
int t = 0;
memset(store, 1, LEN * LEN * LEN);
init(data, store);
/* evolution the number matrix */
upstore(data, store);
/* count the valid one */
for(int i = 0; i < LEN; i++)
for(int j = 0; j < LEN; j++)
{
int c = 0, p;
for(int k = 0; k < LEN; k++)
{
if(store[i][j][k])
p = k;
c += store[i][j][k];
}
if(c == 1)
{
t++;
data[i][j] = p + 1;
}
if(c == 0)
return 0;
}
return t;
}
int research(char in[LEN][LEN])
{
int t = 0, last = -1;
char data[LEN][LEN];
char store[LEN][LEN][LEN];
g_times++;
memcpy(data, in, LEN * LEN);
while(t > last)
{
last = t;
t = evolution(data);
}
if(t == 0)
return 0;
if(t == LEN * LEN)
{
memcpy(in, data, LEN * LEN);
return t;
}
memset(store, 1, LEN * LEN * LEN);
init(data, store);
upstore(data, store);
/* t is not LEN * LEN, continue research */
int min = LEN + 1, li = -1, lj = -1;
/* find one */
for(int i = 0; i < LEN; i++)
for(int j = 0; j < LEN; j++)
{
int c = 0, k;
for(k = 0; k < LEN; k++)
c += store[i][j][k];
if(c == 1)/* do not need to research */
continue;
if(c < min)
{
li = i;
lj = j;
min = c;
}
}
if(min == LEN + 1)
return 0;
while(min--)
{
/* set a possible number */
int k, p = 0;
for(k = 0; k < LEN; k++)
if(store[li][lj][k] == 1)
{
if(p == min)
break;
p++;
}
data[li][lj] = k + 1;
/* start research */
if(LEN * LEN == research(data))
{
memcpy(in, data, LEN * LEN);
return LEN * LEN;
}
}
return 0;
}
void read(char data[LEN][LEN])
{
FILE* file = fopen(".//in.txt", "r");
char buffer[(LEN + 1) * 3] = {0};
if(NULL == file)
exit(0);
int i = 0;
while(fgets(buffer, (LEN + 1) * 3, file))
{
int j = 0;
char* x = strtok(buffer, " ");
do
{
data[i][j++] = atoi(x);
}
while(x = strtok(NULL, " "), x);
i++;
}
fclose(file);
}
int main(int argc, char* argv[])
{
char data[LEN][LEN];
read(data);
if(!research(data))
printf("impossible.\n");
else
{
FILE* file = fopen(".//out.txt", "w+");
for(int i = 0; i < LEN; i++)
{
for(int j = 0; j < LEN; j++)
{
fprintf(file, "%d ", data[i][j]);
printf("%d ", data[i][j]);
}
fprintf(file, "\n");
printf("\n");
}
printf("evolution times: %d\n", g_times);
fprintf(file, "evolution times: %d\n", g_times);
fclose(file);
}
return 0;
}
输入文件:in.txt
0 0 3 5 0 7 0 2 0
0 0 0 0 0 2 0 0 0
0 0 0 0 3 0 9 0 0
7 2 0 0 4 0 0 0 0
0 0 8 0 0 1 0 0 0
9 0 1 0 0 3 0 4 2
0 0 2 7 0 0 8 3 0
6 0 0 0 0 0 0 9 5
0 0 5 0 0 4 0 0 0
输出文件:out.txt
1 8 3 5 9 7 6 2 4
5 6 9 4 1 2 3 7 8
2 7 4 8 3 6 9 5 1
7 2 6 9 4 5 1 8 3
3 4 8 2 7 1 5 6 9
9 5 1 6 8 3 7 4 2
4 1 2 7 5 9 8 3 6
6 3 7 1 2 8 4 9 5
8 9 5 3 6 4 2 1 7
evolution times: 35
果然难的变态……居然要猜测35次
http://www.sudoku.name/sudoku-solver/cn
这个上面的解算算法真是有点白痴阿,
0 0 7 0 0 0 0 5 0
0 0 6 0 0 3 0 0 0
0 2 0 0 7 0 0 1 0
0 9 0 0 0 0 3 0 0
4 0 0 0 1 0 0 0 8
0 0 1 9 0 0 0 7 0
0 4 0 0 3 0 0 2 0
0 0 0 7 0 0 6 0 0
0 1 0 0 0 0 8 0 0
居然解算了足足30多秒......
我的解算是0ms......
有兴趣的朋友可以稍微改一下程序把上面那个所有的可能情况都打印出来
9 3 7 1 8 4 2 5 6
1 5 6 2 9 3 7 8 4
8 2 4 6 7 5 9 1 3
5 9 8 4 2 7 3 6 1
4 7 2 3 1 6 5 9 8
3 6 1 9 5 8 4 7 2
6 4 5 8 3 9 1 2 7
2 8 9 7 4 1 6 3 5
7 1 3 5 6 2 8 4 9
evolution times: 223
传说中人算需要3天的数独。。
8 0 0 0 0 0 0 0 0
0 0 3 6 0 0 0 0 0
0 7 0 0 9 0 2 0 0
0 5 0 0 0 7 0 0 0
0 0 0 0 4 5 7 0 0
0 0 0 1 0 0 0 3 0
0 0 1 0 0 0 0 6 8
0 0 8 5 0 0 0 1 0
0 9 0 0 0 0 4 0 0
很强大,0 秒解出
8 1 2 7 5 3 6 4 9
9 4 3 6 8 2 1 7 5
6 7 5 4 9 1 2 8 3
1 5 4 2 3 7 8 9 6
3 6 9 8 4 5 7 2 1
2 8 7 1 6 9 5 3 4
5 2 1 9 7 4 3 6 8
4 3 8 5 2 6 9 1 7
7 9 6 3 1 8 4 5 2
evolution times: 1762
这个是真变态……1762次啊!!!