回溯法解数独

欢迎吹毛求疵   QQ:1423173783   邮箱:1423173783@qq.com

//代码修改后可以依次输出填数顺序,哪一个空填了哪一个数,保存在vstart中  subtraction()精简后不会直接递归调用使得逻辑思想清楚,效率差多少不清楚,估计相差不大  解决芬兰那题用时620ms
//  storage[10][10]  probable[10][10]的设置给调试带来了方便,开始时全封装在一个结构体二维数组中。
#include<iostream>
#include<fstream>
#include<vector>
#include<time.h>
#include<cstdlib>
using namespace std;
struct{                       //考虑到原来用结构体,这里就没变只是在原来的基础上改动,估计时间复杂度也没啥变化。
    int semaphore[10];
 } node[10][10];
int probable[10][10],storage[10][10];
int finished=0,num=0;      //num=0原来是调试用的,这里没删除。
ofstream out_stream;
vector<int>  must_add1;    //must_add1,must_add2是subtraction用来保存作业记录用的,作业记录保存在must_add2中,恢复也从must_add2中恢复
vector<vector<int>> vstart,must_add2;//vstart用来存储 填格子的先后顺序  (i,j) 填了k
void fills_up();
void subtraction(int row,int col,int k);
void add(int k);
void print_storage();
void print_probable();
void DFS();
int solve();
void fills_up()
{
 for(int i=1;i<=9;i++)
  for(int j=1;j<=9;j++)
  {
   for(int k=1;k<=9;k++)
       {
           node[i][j].semaphore[k]=1;
     }
            storage[i][j]=0;
   probable[i][j]=9;
  }
}
void subtraction(int row,int col,int k)
{
 finished++;
 for(int j=1;j<=9;j++)
  if(node[row][j].semaphore[k]==1) 
         {
    must_add1.push_back((row-1)*9+j);
    node[row][j].semaphore[k]--;
    probable[row][j]--;
      }
 for(int i=1;i<=9;i++)
  if(node[i][col].semaphore[k]==1) 
        {
    must_add1.push_back((i-1)*9+col);
       node[i][col].semaphore[k]--;
    probable[i][col]--;
      }
   int rom=(row-1)/3*3+1+(col-1)/3;
   int row_room=(rom-1)/3*3+1,col_room=(rom-1)%3*3+1;
   for(int i=row_room;i<=row_room+2;i++)
    for(int j=col_room;j<=col_room+2;j++)
     if(node[i][j].semaphore[k]==1)
          {
      must_add1.push_back((i-1)*9+j);
      node[i][j].semaphore[k]--;
      probable[i][j]--;
       }
   if(must_add1.size()==0)  must_add1.push_back(0);
   must_add2.push_back(must_add1);
   must_add1.clear();
}
void add(int k)
{
 finished--;
 int t=must_add2.size()-1,row,col;
 if(must_add2[t][0]==0)  { must_add2.pop_back();return;}
 for(int j=must_add2[t].size()-1;j>=0;j--)
 {
  row=(must_add2[t][j]-1)/9+1;   col=must_add2[t][j]-9*(row-1);
  node[row][col].semaphore[k]++;
  probable[row][col]++;
 }
 must_add2.pop_back();
}
void print_storage()

 out_stream<<"print storage"<<endl;
   for(int i=1;i<=9;i++)
     {
    for(int j=1;j<=9;j++)
     {
   out_stream<<storage[i][j]<<" ";
     if(j%3==0) out_stream<<"   ";
     }   
    out_stream<<endl;
    if(i%3==0)  out_stream<<endl;
     }
   out_stream<<endl<<endl;
}
void print_probable()

 out_stream<<"print probable"<<endl;
   for(int i=1;i<=9;i++)
     {
    for(int j=1;j<=9;j++)
     {
   out_stream<<probable[i][j]<<" ";
     if(j%3==0) out_stream<<"   ";
     }   
    out_stream<<endl;
    if(i%3==0)  out_stream<<endl;
     }
   out_stream<<endl<<endl;
}
void DFS()
{
 int count=10,row=-1,col;
 for(int i=1;i<=9;i++)
   for(int j=1;j<=9;j++)
    if(probable[i][j]<=count && storage[i][j]==0)
    { 
     count=probable[i][j];
     row=i;
     col=j;
    }
    if(row==-1) throw(1);
 if(count==0)  return;
 for(int k=1;k<=9;k++)
  if(node[row][col].semaphore[k]==1)
  {
   vector<int> v1;
   int must_recover[12]={0};
   for(int i=1;i<=9;i++)
    must_recover[i]=node[row][col].semaphore[i];
   must_recover[10]=storage[row][col];
   must_recover[11]=probable[row][col];
   for(int i=1;i<=9;i++)
    node[row][col].semaphore[i]=0;
   storage[row][col]=k;
   probable[row][col]=0;
   v1.push_back(row);  v1.push_back(col);  v1.push_back(k);  vstart.push_back(v1); v1.clear();
   subtraction(row,col,k);
   DFS();
   add(k); vstart.pop_back();
   for(int i=1;i<=9;i++)
    node[row][col].semaphore[i]=must_recover[i];
   storage[row][col]=must_recover[10];
   probable[row][col]=must_recover[11];
  }
}
int solve()
{
 try
 {
   DFS();
   return(0);
 }
 catch(int)
 {
  return(1);
 }
}
int main()
{
 long time;
    int int_start[82];
 ifstream cin_stream;
 vector<int> v1;
 cin_stream.open("d:\\c++\\数独12\\question\\fenlan2.txt");
 for(int i=1;i<82;i++)
  cin_stream>>int_start[i];
 for(int i=1;i<82;i++)
 {
  int row,col;
  if(int_start[i]!=0)
  {
  row=(i-1)/9+1;
  col=i-9*(row-1);
  v1.push_back(row);
  v1.push_back(col);
  v1.push_back(int_start[i]);
  vstart.push_back(v1);
  v1.clear();
  }
 }
 cin_stream.close();
 out_stream.open("d:\\c++\\数独12\\question\\question475.txt");
 time=clock(); 
 fills_up();
 for(int i=0;i<vstart.size();i++)
 {
  for(int k=1;k<=9;k++)
      node[vstart[i][0]][vstart[i][1]].semaphore[k]=0;
  probable[vstart[i][0]][vstart[i][1]]=0;
  storage[vstart[i][0]][vstart[i][1]]=vstart[i][2];
 }
 //print_storage();//这里是输出题目,看看自己输入是否正确
 for(int i=0;i<vstart.size();i++)
  subtraction(vstart[i][0],vstart[i][1],vstart[i][2]);
 //print_storage();//这里是不用技巧时得到的解题结果
 if(finished==81)  return(0);
 solve();
    //print_storage(); //输出解题结果
 //out_stream<<endl;
    time=clock()-time;
    out_stream<<"用时(不含输入数据时间)"<<time/1000<<"秒"<<time%1000<<"毫秒"<<endl;
 cout<<"right"<<endl;
    out_stream.close();
    for(int i=0;i<=80;i++)  //输出解题填数顺序
    {
   cout<<vstart[i][0]<<"    "<<vstart[i][1]<<"       "<<vstart[i][2]<<endl;
    }
    cout<<endl;
 system("pause");
 }

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值