http://blog.sina.com.cn/s/blog_51cea4040100gxn1.html 下面內容是此鏈接的作者發給我的,可能是ccy自己寫的也可能是她的朋友寫的。
QQ及郵箱:1 4 2 3 1 7 3 7 8 3 @qq.com 歡迎吹毛求疵。
//fenlan那題約500ms
//測試預計耗時14h(同方預測試) 11-20 17:44------ 實際耗時約14h
#include <iostream>
#include<time.h>
#include<cstdlib>
#include<fstream>
#define s 3
#define ss s*s
using namespace std;
#define BLANKS 55
#define FAIL 20
int table[9][9],table_for_solve[9][9],solves=0,op=1;
fstream out_stream;
int h[ss][ss],ans=0;
bool b[ss][ss+1],c[ss][ss+1],d[ss][ss+1];
int a[9][9]={
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};
void shuffle(int arr[], int n);
bool test(int x, int y, int v);
bool put(int line, int index);
bool put_line(int line);
void DFS();
int check(int y,int x,int *mark) ; //求probable[y][x] 並且mark[]中爲0的元素說明可以試探
int solve22();
bool create_game(int blanks);
void create_gameover();
void print_all(int k); //輸出到文件
void print_table_for_solve();
void copy(int a[9][9],int b[9][9]);
void make(int,int,int,bool);
bool work(int,int,int);
void score();
int test();
bool fun( int a[10]);
void shuffle(int arr[], int n)
{
int tmp, rd;
for(int i = 0; i < n; i++)
{
rd = rand() % 9;
tmp = arr[rd];
arr[rd] = arr[i];
arr[i] = tmp;
}
}
bool test(int x, int y, int v)
{
int _x = x / 3 * 3;
int _y = y / 3 * 3;
for(int i = _x; i < _x + 3; i++) //測試3 * 3矩陣內是否有重複的數
{
for(int j = _y; j < _y + 3; j++)
{
if(table[i][j] == v)
{
return false;
}
}
}
for(int i = 0; i < 9; i++) //測試橫向、縱向是否有重複的數
{
if(table[x][i] == v || table[i][y] == v)
return false;
}
return true;
}
bool put(int line, int index)
{
if(index > 8)
return true;
int num[] = {1,2,3,4,5,6,7,8,9};
//打亂當前準備寫入數字的前後順序
shuffle(num, 9);
for(int i = 0; i < 9; i++)
//測試數字是否允許填入當前方格
if( test(line, index, num[i]) == true )
{
table[line][index] = num[i];
//填入成功則處理下一個方格
if( put(line, index + 1) == true )
{
return true;
}
}
table[line][index] = 0; //失敗後復位
return false;
}
bool put_line(int line)
{
if(line > 8)
return true;
if( put(line, 0) == true )
//當前一行添入完成後,進入下一行再重複處理。
if( put_line(line + 1) == true )
return true;
for(int i = 0; i < 9; i++)
table[line][i] = 0;
return false;
}
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(table_for_solve[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)
{
solves++;
if(solves==2)
throw(1); //如果解法不唯一,不會等到所有解都出來才結束運行, 保留下面的return又能確定是不是隻有唯一解。
return;
}
check(im,jm,mark);
for(i=1;i<=9;++i)
if(mark[i]==0)
{
table_for_solve[im][jm]=i;
DFS();
}
table_for_solve[im][jm]=0;
}
int solve22()
{
try
{
DFS();
solves=0; //調試後發現
return(1);
}
catch(int)
{
solves=0; //調試後發現,solves是全局變量,以後solves越來越大永遠不可能等於2
return(2);
}
}
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[table_for_solve[y][i]]=1;
for(i=0;i<9;++i)
mark[table_for_solve[i][x]]=1;
is=y/3*3;
js=x/3*3;
for(i=0;i<3;++i)
for(j=0;j<3;++j)
mark[table_for_solve[is+i][js+j]]=1;
for(i=1;i<=9;++i)
if(mark[i]==0)
count++;
return count;
}
bool create_game(int blanks)
{
int i,k,row,col,tmp;
for( i=1;i<=blanks;i++)
{
int num=0;
do
{
do
{
k=rand()%81;
row=k/9;
col=k-9*row;
tmp=table[row][col];
}while(tmp==0);
table[row][col]=0;
copy(table_for_solve,table);
num++;
if(num==FAIL) return(false);
}while((solve22()==2)? table[row][col]=tmp : 0);
}
if(i==blanks+1) return (true);
}
void create_gameover()
{
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
table[i][j]=0;
for(int i = 0; i < 9; i++)
table[0][i] = i + 1;
shuffle(table[0], 9);
//從第二行開始添入數字
while(!put_line(1)) ;
}
void print_all(int k)
{
for(int i=1;i<=9;i++)
{
if(i%3==1) out_stream<<endl;
for(int j=1;j<=9;j++)
{
if(j%3==1) out_stream<<" ";
out_stream<<table[i-1][j-1];
}
out_stream<<endl;
}
out_stream<<endl<<endl;
}
void print_table_for_solve()
{
for(int i=1;i<=9;i++)
{
if(i%3==1) out_stream<<endl;
for(int j=1;j<=9;j++)
{
if(j%3==1) out_stream<<" ";
out_stream<<table_for_solve[i-1][j-1];
}
out_stream<<endl;
}
out_stream<<endl<<endl;
}
void copy(int a[9][9],int b[9][9])
{
for(int i=0;i<=8;i++)
for(int j=0;j<=8;j++)
a[i][j]=b[i][j];
}
void make(int x,int y,int i,bool z)
{
b[x][i]=z;
c[y][i]=z;
d[x/s*s+y/s][i]=z;
}
bool work(int x,int y,int z)
{
int i;
if (y==9)
x++,y=0;
if (x==9)
{
ans=z;
return(true);
}
if (table_for_solve[x][y])
{
if(work(x,y+1,z+table_for_solve[x][y]*h[x][y]))
return(true);
else return(false);
}
else
{
for (i=1;i<=ss;i++)
if (!b[x][i]&&!c[y][i]&&!d[x/s*s+y/s][i])
{
table_for_solve[x][y]=i;
make(x,y,i,1);
if(work(x,y+1,z+i*h[x][y]))
return(true);
make(x,y,i,0);
}
table_for_solve[x][y]=0;
return(false);
}
}
void score()
{
int i,j;
for (i=0;i<ss;i++)
for (j=0;j<ss;j++)
{
if (i==0||j==0||i==8||j==8)
h[i][j]=6;
else if (i==1||j==1||i==7||j==7)
h[i][j]=7;
else if (i==2||j==2||i==6||j==6)
h[i][j]=8;
else if (i==3||j==3||i==5||j==5)
h[i][j]=9;
else
h[i][j]=10;
}
}
int test()
{
int sum=0,i,j,aray[10];
for(int i=1;i<=9;i++)
{
sum=0;
for(int j=1;j<=9;j++)
{ sum+=table_for_solve[i-1][j-1]; aray[j]=table_for_solve[i-1][j-1];}
if(sum!=45) {cout<<"wrong"<<endl; return 0;}
if(!fun(aray)) return 0;
}
for( j=1;j<=9;j++)
{
sum=0;
for(i=1;i<=9;i++)
{ sum+=table_for_solve[i-1][j-1]; aray[i]=table_for_solve[i-1][j-1];}
if(sum!=45) {cout<<"wrong"<<endl; return 0;}
if(!fun(aray)) return 0;
}
for(int k=1;k<=9;k++)
{
sum=0;
int row=(k-1)/3*3+1,col=(k-1)%3*3+1,sub=1;
for(i=row;i<=row+2;i++)
for(j=col;j<=col+2;j++)
{ sum+=table_for_solve[i-1][j-1]; aray[sub++]=table_for_solve[i-1][j-1];}
if(sum!=45) {cout<<"wrong"<<endl; return 0;}
if(!fun(aray)) return 0;
}
return 1;
}
bool fun(int a[10])
{
int i,j;
for(i=1;i<=8;i++)
{
if(*(a+i)==0) continue;
for(j=i+1;j<=9;j++)
if(*(a+i)==*(a+j)) return (false);
}
return (true);
}
int main()
{
out_stream.open("d:\\c++\\數獨12\\question\\question473.txt");
srand(time(0));
long time1,time2;
time1=clock();
while (op<=1000000)
{
if (op==1000001) break;
create_gameover();
while(!create_game(BLANKS))
create_gameover();
memset(table_for_solve,0,sizeof(table_for_solve));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
score();
for (int i=0;i<ss;i++)
for (int j=0;j<ss;j++)
if (table[i][j])
{
table_for_solve[i][j]=table[i][j];
make(i,j,table_for_solve[i][j],1);
}
;
work(0,0,0);
if (ans && test() ) ;
//print_table_for_solve();
else { out_stream<<"第"<<op<<"題測試不通過"; print_all(1); print_table_for_solve();}
op++; ans=0;
}
time2=clock();
out_stream<<time2-time1<<"ms"<<endl;
out_stream.close();
}