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