欢迎吹毛求疵:QQ:1423173783 邮箱:1423173783@qq.com
//http://blog.youkuaiyun.com/nhczp/article/details/1498868源地址
//程序摘自上面网页上的博客,向它表示尊敬. 程序在文件中的输出格式:如果题目是给定的,就先输出题目后输出结果,如果是指定空格数,就生成出题目的一个终盘,然后输出挖过洞的题目,最后输出结果。输出结果分为一解和多解,一解就输一个解多解会全输出
//这代码很简单,map只用来存储所填的值,没有给9个候选数设置空间,不用减候选数不用恢复候选数,实践证明它解决data4(芬兰)那题用来100多ms,还有一特点是,本代码可以验证一个题目是否有多解。
#include "time.h"
#include<cstdlib>
#include<iostream>
#include<fstream>
using namespace std;
ofstream out_stream;
enum{ANY=0,ALL=1};
int map[9][9];
int smod;
int solves;
int check(int,int,int*);
void dfs();
void CSudoku(int n=40);// 随机生成数独,n越大越难
void CSudoku(int *data);// 人工指定数独
void display();
void print_all();
int resolve(int mod=ALL);// 解数独
void CSudoku(int n)
{
int i,j;
srand(time(0));
do
{
for(i=0;i<9;++i)
{
for(j=0;j<9;++j)
map[i][j]=0;
j=rand()%9;
map[i][j]=i+1;
}
}
while(!resolve(ANY));
for(int k=0;k<n;) // 挖窟窿
{
i=rand()%81;
j=i%9;
i=i/9;
if(map[i][j]>0)
{
map[i][j]=0;
++k;
}
}
//printf("(randomized sudoku created with %d blanks.)/n",blanks);
}
void CSudoku(int *data)
{
int *pm=(int*)map;
for(int i=0;i<81;++i)
pm[i]=data[i];
}
/*void CSudoku::display()
{
printf("┏━┯━┯━┳━┯━┯━┳━┯━┯━┓\n");
for(int i=0;i<9;++i)
{
for(int j=0;j<9;++j)
{
if(map[i][j]>0)
{
if(j%3==0)
printf("┃ %d",map[i][j]);
else
printf("│ %d",map[i][j]);
}
else
{
if(j%3==0)
printf("┃ ");
else
printf("│ ");
}
}
printf("┃\n");
if (i!=8)
{
if((i+1)%3==0)
printf("┣━┿━┿━╋━┿━┿━╋━┿━┿━┫\n");
else
printf("┠─┼─┼─╂─┼─┼─╂─┼─┼─┨\n");
} }
printf("┗━┷━┷━┻━┷━┷━┻━┷━┷━┛\n");
}*/
void display()
{
out_stream<<"┏━┯━┯━┳━┯━┯━┳━┯━┯━┓"<<endl;
for(int i=0;i<9;++i)
{
for(int j=0;j<9;++j)
{
if(map[i][j]>0)
{
if(j%3==0)
out_stream<<"┃ "<<map[i][j];
else
out_stream<<"│ "<<map[i][j];
}
else
{
if(j%3==0)
out_stream<<"┃ ";
else
out_stream<<"│ ";
}
}
out_stream<<"┃"<<endl;
if (i!=8)
{
if((i+1)%3==0)
out_stream<<"┣━┿━┿━╋━┿━┿━╋━┿━┿━┫"<<endl;
else
out_stream<<"┠─┼─┼─╂─┼─┼─╂─┼─┼─┨"<<endl;
} }
out_stream<<"┗━┷━┷━┻━┷━┷━┻━┷━┷━┛"<<endl;
}
void print_all()
{
out_stream<<"print storage"<<endl;
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
out_stream<<map[i-1][j-1]<<" ";
if(j%3==0) out_stream<<" ";
}
out_stream<<endl;
if(i%3==0) out_stream<<endl;
}
out_stream<<endl<<endl;
}
int resolve(int mod)
{
smod=mod;
if(mod==ALL)
{
solves=0;
dfs();
return solves;
}
else if(mod==ANY)
{
try
{
dfs();
return 0;
}
catch(int) {return (1);}
}
return 0;
}
int check(int y,int x,int *mark) //求probable[y][x]
{
int i,j,is,js,count=0;
for(i=1;i<=9;++i)
mark[i]=0;
for(i=0;i<9;++i)
mark[map[y][i]]=1;
for(i=0;i<9;++i)
mark[map[i][x]]=1;
is=y/3*3;
js=x/3*3;
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
mark[map[is+i][js+j]]=1;
}
for(i=1;i<=9;++i)
if(mark[i]==0)
count++;
return count;
}
void dfs()
{
int i,j,im=-1,jm,min=10;
int mark[10];
for(i=0;i<9;++i)
{
for(j=0;j<9;++j)
{
if(map[i][j])
continue;
int c=check(i,j,mark);
if(c==0)
return;
if(c<=min)
{
im=i;
jm=j;
min=c;
}
}
}
if(im==-1)
{
if(smod==ALL)
{
printf("No. %d:/n",++solves);
printf("\n");
display();
//print_all();
return;
}
else if(smod==ANY)
{
display();
throw(1);
}
}
check(im,jm,mark);
for(i=1;i<=9;++i)
{
if(mark[i]==0)
{
map[im][jm]=i;
dfs();
}
}
map[im][jm]=0;//当map[im][jm]填任何数都错都不行,说明前面填错了,要往前回溯。
}
int main()
{
int data1[]=
{4,9,0,0,0,6,0,2,7,
5,0,0,0,1,0,0,0,4,
6,0,0,0,0,8,0,0,3,
1,0,4,0,0,0,0,0,0,
0,6,0,0,0,0,0,5,0,
0,0,0,0,0,0,2,0,8,
7,0,0,2,0,0,0,0,5,
8,0,0,0,9,0,0,0,1,
3,4,0,5,0,0,0,6,2
};
int data2[]=
{7,4,0,0,8,0,0,1,6,
9,0,0,0,3,5,0,0,4,
0,0,0,7,0,0,0,0,0,
0,7,0,0,0,9,5,0,0,
6,1,0,0,5,0,0,8,7,
0,0,2,6,0,0,0,4,0,
0,0,0,0,0,4,0,0,0,
3,0,0,5,6,0,0,0,2,
5,6,0,0,1,0,0,3,9
};
int data3[]=
{1,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0
};
int data4[]= //芬兰那道超难题
{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
};
int data5[]=
{0,0,2,6,0,0,0,0,1,
0,8,0,0,0,0,7,0,0,
5,6,7,1,0,0,3,0,0,
0,4,0,2,0,0,8,0,0,
6,0,8,0,9,1,0,0,4,
0,2,5,0,0,3,6,9,7,
0,0,4,5,0,0,0,0,0,
0,0,0,0,0,0,0,0,5,
9,5,0,4,0,6,0,0,0
};
enum{ANY=0,ALL=1};
int blanks;
long time;
out_stream.open("d:\\c++\\数独12\\question\\question474.txt");
cout<<"随机生成一个数独,输入空格数";
cin>>blanks;
// dir c:\windows\system32 >>d:\\c++\\sudoku(class)_generate(solve)_dfs\\question1.txt;
CSudoku (data4);
// s.display();
display();
cout<<"开始解数独:"<<endl;
time=clock();
cout<< resolve(ALL)<<endl;
out_stream.close();
time=clock()-time;
cout<<"use time"<<time/1000<<"s"<<time%1000<<"ms"<<endl;
system("pause");
}