generate(粗糙) and solve(DFS) 数独(9*9)

欢迎吹毛求疵: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");
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值