QQ及邮箱:1 4 2 3 1 7 3 7 8 3 @qq.com欢迎吹毛求疵。
#include<iostream>
#include<fstream>
#include<vector>
#include<time.h>
#include<cstdlib>
using namespace std;
struct{
int semaphore[11];//semaphore[10]表示存储值
int probable;
int semaphore_explore_recover[10];
int probable_explore_recover;
int explore[10];//每个节点node都可能被用来作为探索节点,探索时从该节点可能取值的数字(1--9)从小到大依次探索,当一个节点所有取值探索过后都出现错误(即该节点不能去任何值)这表明这个探索节点不能取任何值是上一步的错误造成的,应该回溯进一步往前恢复。而要判断该探索节点任何值都不能取就必须设一个长度为9的数组,如果数组的每个元素都为0表示每个取值探索过后都不成功,即需要进一步往前回溯。
} node[10][10];
int finished=0,count=0;
ofstream out_stream;
vector<int> v1;
vector<vector<int>> v2,success;
vector<vector<vector<int>>> v3;
typedef struct {
int row;
int col;
int probable;
} sign;
sign min_probable_node={{0},{0},{10}};
int room_subscript[2]={0},semaphore[10]={0}; //room_subscript[0]存某个宫的行起始号,room_subscript[1]存某宫的列起始号,semaphore[0]存储node[row][col].semaphore[1]~node[row][col].semaphore.semaphore[9]中不为0的个数,后面的依次存入不为0的k值,有几个k值不为0就存几个k值。
int room(int row,int col); //返回node[row][col]所在的宫号
int* room(int k); //返回宫K的行起始号和列起始号,它们分别存储在全局数组中subscript[2]
void fills_up(); //开始时要初始化node[10][10],使得每个节点的候选数semaphore[1--9]全为1,probable为9,填写值semaphore[10]为0;探索候选数semaphore_explore_recover[1--9]全为0值,probable_explore_recover为0,探索记录数组explore[1--9]全为0
void subtracion(int row,int col,int storage); //当node[row][col]只有一个候选数可填,且知道这个候选数,调用此函数(非回溯版)(storage要换成k就显得统一,易理解,但原来是这样设置的,考虑到只是一个形参生命力只在一个函数内这里不做改动,它表示node[row][col]填入storage值,并且正要减去所在行列区的其它格的候选数storage
vector<vector<int>> subtracion(int row,int col);//当node[row][col]只有一个候选数可填,且知道这个候选数,调用此函数(回溯版)
void call_subtraction(int row,int col,int recall);//当node[row][col]的一个候选数被减,只剩下一个候选数可填,但又不知道是哪个候选数时调用此函数,recall=1表示用回溯版
void row_technology(int row,int m,int recall); //对第row行的没有填的m候选数 看看它是不是只能填在某一格上,或只能填在某一宫的格中,recall=1表示用回溯版
void col_technology(int col,int m,int recall); //对第col列的没有填的m候选数 看看它是不是只能填在某一格上,或只能填在某一宫的格中,recall=1表示用回溯版
void room_technology(int i,int m,int recall); //对第i宫的没有填的m候选数 看看它是不是只能填在某一格上,或只能填在宫的某一行或列中,recall=1表示用回溯版
void row_technology(int row ,int recall); //对第row行所有没有填的每一个数(即候选数)看看它是不是只能填在某一格上,或只能填在某一宫的格中,recall=1表示用回溯版
void col_technology(int col,int recall); //对第col行所有没有填的每一个数(即候选数)看看它是不是只能填在某一格上,或只能填在某一宫的格中,recall=1表示用回溯版
void room_technology(int i,int recall); //对第i宫所有没有填的每一个数(即候选数)看看它是不是只能填在某一格上,或只能填在宫的某一行或列中,recall=1表示用回溯版
int find_partner(vector<int> v1); //对给出的v1在v2中找到它的匹配项,即找出v1是被谁调用的返回值
void add(int row,int col,int storage,int semaphore,vector<int> must_add1,vector<int> must_add2);//node[row][col]不能填storage所以要恢复,恢复在must_add2不在must_add1中的节点,如果semaphore为2表示两个v1直接匹配,node[row][col]本身要恢复,semaphore=3表示恢复涉及到3个v1 node[row][col]本身则不恢复。
void addv2(vector<vector<int>> & v2); //explore()在min_probable_node的某个k(候选数)上探测得到错误结果,这时所有的探索记录保存在全局变量v2中,由于传址调用所以全局变量v2会被修改。
void print_all(); //输出当时状态下的九宫格的所有已填数(输出到写出文件中,这个输出对象可以改的),不管是调试用,还是最后给出正确答案,还是一切要得到中间结果的状态下都能用到它,
void copy(vector<vector<int>> vec) ; //把vector<vector<int>> 变量复制到全局变量v2中
void explore(); //当所有技巧或模式都用到极致时(当然也可以不用到极致,有时回溯法要来得更快,或者遍历模式耗时太长还不如回溯来得快,当然解题高手的兴奋点是最短时间发现已经知道的最难的推理模式,或发现新的不同难度系数的推理模式)要用回溯法(回溯法可嵌入技巧,一般以常用到遍历耗时短的技巧嵌入为佳),回溯法没有返回值,没有参数,形参其实就是全局变量v2,v1,返回值其实是全局变量finished
int test(); //当题目解完时检测题目有没有解错,方法是每行每列每宫的和都要是45.其实技巧法和回溯法都能用数学证明,只要填满81个格就一定是正确的,但这个函数耗时不到1毫秒 就保存了下来。
bool fun( int array[10]); //数组array的九个数如有重复返回false
bool row_col_room_technology_solve() ; //最简单的行列宫互相影响技巧遍历 ,如果题解出来就返回true,如果解不出来是遍历后解不出来说明题目中没有适用的简单模式
int room(int row,int col)
{
return((row-1)/3*3+1+(col-1)/3);
}
int* room(int k)
{
room_subscript[0]=(k-1)/3*3+1;
room_subscript[1]=(k-room_subscript[0])*3+1;
return (room_subscript);
}
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;
node[i][j].semaphore_explore_recover[k]=0;
node[i][j].explore[k]=0;
}
node[i][j].semaphore[10]=0;
node[i][j].probable=9;
node[i][j].probable_explore_recover=0;
}
}
void subtraction(int row,int col,int storage)
{
finished++;
for(int j=1;j<=9;j++)
if(node[row][j].semaphore[storage]==1)
{
node[row][j].semaphore[storage]=0; //把节点中不能填的点排除
node[row][j].probable-=1; //probable即可能填的数目减1
if(node[row][j].probable==1)
{
for(int k=1;k<=9;k++)
if(node[row][j].semaphore[k]==1)
{
out_stream<<"唯一数:"<<char(row-1+'A')<<j<<"应填"<<k<<"。"<<endl;
cout<<"唯一数:"<<char(row-1+'A')<<j<<"应填"<<k<<"。"<<endl;
node[row][j].semaphore[10]=k;
node[row][j].semaphore[k]=0;
node[row][j].probable=0;
subtraction(row,j,k);
}
}
}
for(int i=1;i<=9;i++)
if(node[i][col].semaphore[storage]==1)
{
node[i][col].semaphore[storage]=0; //把节点中不能填的点排除
node[i][col].probable-=1; //probable即可能填的数目减1
if(node[i][col].probable==1)
{
for(int k=1;k<=9;k++)
if(node[i][col].semaphore[k]==1)
{
out_stream<<"唯一数:"<<char(i-1+'A')<<col<<"应填"<<k<<"。"<<endl;
cout<<"唯一数:"<<char(i-1+'A')<<col<<"应填"<<k<<"。"<<endl;
node[i][col].semaphore[10]=k;
node[i][col].semaphore[k]=0;
node[i][col].probable=0;
subtraction(i,col,k);
}
}
}
for(int i=(row-1)/3*3+1;i<=(row-1)/3*3+3;i++)
for(int j=(col-1)/3*3+1 ;j<=(col-1)/3*3+3;j++)
if(node[i][j].semaphore[storage]==1)
{
node[i][j].semaphore[storage]=0; //把节点中不能填的点排除
node[i][j].probable-=1; //probable即可能填的数目减1
if(node[i][j].probable==1)
{
for(int k=1;k<=9;k++)
if(node[i][j].semaphore[k]==1)
{
out_stream<<"唯一数:"<<char(i-1+'A')<<j<<"应填"<<k<<"。"<<endl;
cout<<"唯一数:"<<char(i-1+'A')<<j<<"应填"<<k<<"。"<<endl;
node[i][j].semaphore[10]=k;
node[i][j].semaphore[k]=0;
node[i][j].probable=0;
subtraction(i,j,k);
}
}
}
}
vector<vector<int>> subtraction(int row,int col)
{
finished++;
if(finished==81) return success;
vector<int> must_add;
for(int j=1;j<=9;j++)
if(node[row][j].semaphore[node[row][col].semaphore[10]]==1 && node[row][j].probable!=0)
{
must_add.push_back(row);
must_add.push_back(j);
node[row][j].semaphore[node[row][col].semaphore[10]]=0; //把节点中不能填的点排除
node[row][j].probable-=1; //probable即可能填的数目减1
if(node[row][j].probable==1)
{
for(int k=1;k<=9;k++)
if(node[row][j].semaphore[k]==1)
{
for(int m=1;m<=9;m++)
if(k==node[row][m].semaphore[10] && m!=j)
{
must_add.push_back(100);
v2.push_back(must_add);
v1.push_back(row);
v1.push_back(j);
v1.push_back(0);
v1.push_back(100);
v2.push_back(v1);
v1.clear();
return v2;
}
for(int m=1;m<=9;m++)
if(k==node[m][j].semaphore[10] && m!=row)
{
must_add.push_back(100);
v2.push_back(must_add);
v1.push_back(row);
v1.push_back(j);
v1.push_back(0);
v1.push_back(100);
v2.push_back(v1);
v1.clear();
return v2;
}
for(int m=(row-1)/3*3+1;m<=(row-1)/3*3+3;m++)
for(int n=(j-1)/3*3+1;n<=(j-1)/3*3+3;n++)
if(k==node[m][n].semaphore[10] && !(m==row && n==j))
{
must_add.push_back(100);
v2.push_back(must_add);
v1.push_back(row);
v1.push_back(j);
v1.push_back(0);
v1.push_back(100);
v2.push_back(v1);
v1.clear();
return v2;
}
node[row][j].semaphore[10]=k;
node[row][j].semaphore[k]=0;
node[row][j].probable=0;
must_add.push_back(10);
v2.push_back(must_add);
v1.push_back(row);
v1.push_back(j);
v1.push_back(node[row][j].semaphore[10]);
v1.push_back(10);
v2.push_back(v1);
v1.clear();
subtraction(row,j);
if(v2[v2.size()-1][3]!=400 )
goto loop;
else
must_add.pop_back();
}
}
}
for(int i=1;i<=9;i++)
if(node[i][col].semaphore[node[row][col].semaphore[10]]==1 && node[i][col].probable!=0)
{
must_add.push_back(i);
must_add.push_back(col);
node[i][col].semaphore[node[row][col].semaphore[10]]=0; //把节点中不能填的点排除
node[i][col].probable-=1; //probable即可能填的数目减1
if(node[i][col].probable==1)
{
for(int k=1;k<=9;k++)
if(node[i][col].semaphore[k]==1)
{
for(int m=1;m<=9;m++)
if(k==node[i][m].semaphore[10] && m!=col)
{
must_add.push_back(200);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(col);
v1.push_back(0);
v1.push_back(200);
v2.push_back(v1);
v1.clear();
return v2;
}
for(int m=1;m<=9;m++)
if(k==node[m][col].semaphore[10] && m!=i)
{
must_add.push_back(200);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(col);
v1.push_back(0);
v1.push_back(200);
v2.push_back(v1);
v1.clear();
return v2;
}
for(int m=(i-1)/3*3+1;m<=(i-1)/3*3+3;m++)
for(int n=(col-1)/3*3+1;n<=(col-1)/3*3+3;n++)
if(k==node[m][n].semaphore[10] && !(m==i && n==col))
{
must_add.push_back(200);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(col);
v1.push_back(0);
v1.push_back(200);
v2.push_back(v1);
v1.clear();
return v2;
}
node[i][col].semaphore[10]=k;
node[i][col].semaphore[k]=0;
node[i][col].probable=0;
must_add.push_back(20);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(col);
v1.push_back(k);
v1.push_back(20);
v2.push_back(v1);
v1.clear();
subtraction(i,col);
if(v2[v2.size()-1][3]!=400 )
goto loop;
else
must_add.pop_back();
}
}
}
for(int i=(row-1)/3*3+1;i<=(row-1)/3*3+3;i++)
for(int j=(col-1)/3*3+1 ;j<=(col-1)/3*3+3;j++)
if(node[i][j].semaphore[node[row][col].semaphore[10]]==1 && node[i][j].probable!=0)
{
must_add.push_back(i);
must_add.push_back(j);
node[i][j].semaphore[node[row][col].semaphore[10]]=0; //把节点中不能填的点排除
node[i][j].probable-=1; //probable即可能填的数目减1
if(node[i][j].probable==1)
{
for(int k=1;k<=9;k++)
if(node[i][j].semaphore[k]==1)
{
for(int m=1;m<=9;m++)
{
if(node[i][m].semaphore[10]==k && m!=j)
{
must_add.push_back(300);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(j);
v1.push_back(0);
v1.push_back(300);
v2.push_back(v1);
v1.clear();
return v2;
}
}
for(int m=1;m<=9;m++)
{
if(node[m][j].semaphore[10]==k && m!=i)
{
must_add.push_back(300);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(j);
v1.push_back(0);
v1.push_back(300);
v2.push_back(v1);
v1.clear();
return v2;
}
}
for(int m=(row-1)/3*3+1;m<=(row-1)/3*3+3;m++)
for( int n=(col-1)/3*3+1;n<=(col-1)/3*3+3;n++)
{
if(k==node[m][n].semaphore[10] && !(m==i && n==j))
{
must_add.push_back(300);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(j);
v1.push_back(0);
v1.push_back(300);
v2.push_back(v1);
v1.clear();
return v2;
}
}
node[i][j].semaphore[10]=k;
node[i][j].semaphore[k]=0;
node[i][j].probable=0;
must_add.push_back(30);
v2.push_back(must_add);
v1.push_back(i);
v1.push_back(j);
v1.push_back(k);
v1.push_back(30);
v2.push_back(v1);
v1.clear();
subtraction(i,j);
if(v2[v2.size()-1][3]!=400 )
goto loop;
else
must_add.pop_back();
}
}
}
must_add.push_back(400);
v2.push_back(must_add);
v1.push_back(row);
v1.push_back(col);
v1.push_back(1);
v1.push_back(400);
v2.push_back(v1);
v1.clear();
loop: if(v2[v2.size()-1][3]>30) return (v2);
else return (success);
}
void call_subtraction(int row,int col,int recall)//recall=0表示技术用,recall=1表示回溯用
{
if(recall==0)
{
for(int k=1;k<=9;k++)
if(node[row][col].semaphore[k]==1)
{
out_stream<<"唯一数:"<<char(row-1+'A')<<col<<"应填"<<k<<"。"<<endl;
cout<<"唯一数:"<<char(row-1+'A')<<col<<"应填"<<k<<"。"<<endl;
node[row][col].semaphore[k]=0;
node[row][col].semaphore[10]=k;
node[row][col].probable=0;
subtraction(row,col,k);
}
}
else if(recall==1)
{
for(int k=1;k<=9;k++)
if(node[row][col].semaphore[k]==1)
{
node[row][col].semaphore[k]=0;
node[row][col].semaphore[10]=k;
node[row][col].probable=0;
subtraction(row,col);
}
}
}
void row_technology(int row,int m,int recall)//m表示候选数 recall=1表示是要回溯
{
int col;
int *p=new int[10];
int sum=0;
for(col=1;col<=9;col++)
if(node[row][col].semaphore[m]==1)
p[sum++]=col;
if(sum==1)//非回溯
{
int* a=new int[10];//p[1]到p[9]如果为1说明会被减去
for(int i=1;i<=9;i++)
a[i]=0;
for(int k=1;k<=m-1;k++)
if(node[row][p[0]].semaphore[k]==1)
{
if(recall)
{
node[row][p[0]].semaphore[k]=0;
node[row][p[0]].probable--;
v1.push_back(row);
v1.push_back(p[0]);
v1.push_back(k);
v1.push_back(11);
v2.push_back(v1);
v1.clear();
}
else
{
a[k]=1;//此时不对要减去的候选数进行操作,把它后延是因为后面还有更诱人的subtraction操作,让它先进行则更快
out_stream<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<p[0]<<"应删"<<k<<"(行"<<char(row-1+'A')<<"只一格能填"<<m<<")。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<p[0]<<"应删"<<k<<"(行"<<char(row-1+'A')<<"只一格能填"<<m<<")。"<<endl;
}
}
for(int k=m+1;k<=9;k++)
if(node[row][p[0]].semaphore[k]==1)
{
if(recall)
{
node[row][p[0]].semaphore[k]=0;
node[row][p[0]].probable--;
v1.push_back(row);
v1.push_back(p[0]);
v1.push_back(k);
v1.push_back(11);
v2.push_back(v1);
v1.clear();
}
else
{
a[k]=1;//此时不对要减去的候选数进行操作,把它后延是因为后面还有更诱人的subtraction操作,让它先进行则更快
out_stream<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<p[0]<<"应删"<<k<<"(行"<<char(row-1+'A')<<"只一格能填"<<m<<")。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<p[0]<<"应删"<<k<<"(行"<<char(row-1+'A')<<"只一格能填"<<m<<")。"<<endl;
}
}
for(col=1;col<=9;col++)
node[row][p[0]].semaphore[col]=0;
node[row][p[0]].probable=0;
node[row][p[0]].semaphore[10]=m;
out_stream<<"唯一数:"<<char(row-1+'A')<<p[0]<<"应填"<<m<<"。"<<endl;
cout<<"唯一数:"<<char(row-1+'A')<<p[0]<<"应填"<<m<<"。"<<endl;
subtraction(row,p[0],m);
for(int k=1;k<=9;k++)
if(a[k]==1)
{
row_technology(row,k,recall);
col_technology(p[0],k,recall);
room_technology(room(row,p[0]),k,recall);
}
delete[] a;
}
else if (sum==2)//非回溯
{
if(room(row,p[0])==room(row,p[1]))
{
int* a=new int[5];
a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0;//a[0],a[1],a[2]对应三列,如为1表示相应的列候选数v[i]肯定被删减,a[3],a[4]对应两行,这两空直接填入删减v[i]候选数的行号,如果没有行被删减v[i]候选数,a[3],a[4]则都为0
int k1=room(room(row,p[0]))[0];
int k2=room(room(row,p[0]))[1];
for(int i=k1;i<=row-1;i++)
for(int j=k2;j<=k2+2;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[j-k2]=1;
if(a[3]==0) a[3]=i;
else if(a[3]!=i) a[4]=i;
}
for(int i=row+1;i<=k1+2;i++)
for(int j=k2;j<=k2+2;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[j-k2]=1;
if(a[3]==0) a[3]=i;
else if(a[3]!=i) a[4]=i;
}
if(a[0]==1) col_technology(k2,m,recall);
if(a[1]==1) col_technology(k2+1,m,recall);
if(a[2]==1) col_technology(k2+2,m,recall);
if(a[3]!=0) row_technology(a[3],m,recall);
if(a[4]!=0) row_technology(a[4],m,recall);
delete[] a;
}
}
else if (sum==3)//非回溯
{
if(room(row,p[0])==room(row,p[1]) && room(row,p[0])==room(row,p[2]))
{
int* a=new int[5];
a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0;//a[0],a[1],a[2]对应三列,如为1表示相应的列候选数v[i]肯定被删减,a[3],a[4]对应两行,这两空直接填入删减v[i]候选数的行号,如果没有行被删减v[i]候选数,a[3],a[4]则都为0
int k1=room(room(row,p[0]))[0];
int k2=room(room(row,p[0]))[1];
for(int i=k1;i<=row-1;i++)
for(int j=k2;j<=k2+2;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[j-k2]=1;
if(a[3]==0) a[3]=i;
else if(a[3]!=i) a[4]=i;
}
for(int i=row+1;i<=k1+2;i++)
for(int j=k2;j<=k2+2;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(行"<<char(row-1+'A')<<"对宫"<<room(row,p[0])<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[j-k2]=1;
if(a[3]==0) a[3]=i;
else if(a[3]!=i) a[4]=i;
}
if(a[0]==1) col_technology(k2,m,recall);
if(a[1]==1) col_technology(k2+1,m,recall);
if(a[2]==1) col_technology(k2+2,m,recall);
if(a[3]!=0) row_technology(a[3],m,recall);
if(a[4]!=0) row_technology(a[4],m,recall);
delete[] a;
}
}
delete[] p;
}
void col_technology(int col,int m,int recall)//m只能填在行的某一空上 或k只能填在这一列的某一宫上,k表示候选数
{
int row;
int *p=new int[10];
int sum=0;
for(row=1;row<=9;row++)
if(node[row][col].semaphore[m]==1)
p[sum++]=row;
if(sum==1)
{
int* a=new int[10];//p[1]到p[9]如果为1说明会被减去
for(int i=1;i<=9;i++)
a[i]=0;
for(int k=1;k<=m-1;k++)
if(node[p[0]][col].semaphore[k]==1)
{
a[k]=1;//此时不对要减去的候选数进行操作,把它后延是因为后面还有更诱人的subtraction操作,让它先进行则更快
out_stream<<"行列区互相影响候选数删减法:"<<char(p[0]-1+'A')<<col<<"应删"<<k<<"(列"<<col<<"只一格能填"<<m<<")。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(p[0]-1+'A')<<col<<"应删"<<k<<"(列"<<col<<"只一格能填"<<m<<")。"<<endl;
}
for(int k=m+1;k<=9 ;k++)
if(node[p[0]][col].semaphore[k]==1)
{
a[k]=1;//此时不对要减去的候选数进行操作,把它后延是因为后面还有更诱人的subtraction操作,让它先进行则更快
out_stream<<"行列区互相影响候选数删减法:"<<char(p[0]-1+'A')<<col<<"应删"<<k<<"(列"<<col<<"只一格能填"<<m<<")。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(p[0]-1+'A')<<col<<"应删"<<k<<"(列"<<col<<"只一格能填"<<m<<")。"<<endl;
}
for(row=1;row<=9;row++)
node[p[0]][col].semaphore[row]=0;
node[p[0]][col].probable=0;
node[p[0]][col].semaphore[10]=m;
out_stream<<"唯一数:"<<char(p[0]-1+'A')<<col<<"应填"<<m<<"。"<<endl;
cout<<"唯一数:"<<char(p[0]-1+'A')<<col<<"应填"<<m<<"。"<<endl;
subtraction(p[0],col,m);
for(int k=1;k<=9;k++)
if(a[k]==1)
{
row_technology(p[0],k,recall);
col_technology(col,k,recall);
room_technology(room(p[0],col),k,recall);
}
delete[] a;
}
else if (sum==2)//非回溯
{
if(room(p[0],col)==room(p[1],col))
{
int* a=new int[5];
a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0;//a[0],a[1],a[2]对应三行,如为1表示相应行的候选数v[i]肯定被删减,a[3],a[4]对应两列,这两空直接填入删减v[i]候选数的列,如果没有列被删减v[i]候选数,a[3],a[4]则都为0
int k1=room(room(p[0],col))[0];
int k2=room(room(p[0],col))[1];
for(int i=k1;i<=k1+2 ;i++)
for(int j=k2;j<=col-1;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[i-k1]=1;
if(a[3]==0) a[3]=j;
else if(a[3]!=j) a[4]=j;
}
for(int i=k1;i<=k1+2 ;i++)
for(int j=col+1;j<=k2+2;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[i-k1]=1;
if(a[3]==0) a[3]=j;
else if(a[3]!=j) a[4]=j;
}
if(a[0]==1) row_technology(k1,m,recall);
if(a[1]==1) row_technology(k1+1,m,recall);
if(a[2]==1) row_technology(k1+2,m,recall);
if(a[3]!=0) col_technology(a[3],m,recall);
if(a[4]!=0) col_technology(a[4],m,recall);
delete[] a;
}
}
else if (sum==3)//非回溯
{
if(room(p[0],col)==room(p[1],col) && room(p[0],col)==room(p[2],col))
{
int* a=new int[5];
a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0;//a[0],a[1],a[2]对应三行,如为1表示相应行的候选数v[i]肯定被删减,a[3],a[4]对应两列,这两空直接填入删减v[i]候选数的列,如果没有列被删减v[i]候选数,a[3],a[4]则都为0
int k1=room(room(p[0],col))[0];
int k2=room(room(p[0],col))[1];
for(int i=k1;i<=k1+2 ;i++)
for(int j=k2;j<=col-1;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[i-k1]=1;
if(a[3]==0) a[3]=j;
else if(a[3]!=j) a[4]=j;
}
for(int i=k1;i<=k1+2 ;i++)
for(int j=col+1;j<=k2+2;j++)
if(node[i][j].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(i-1+'A')<<j<<"应删"<<m<<"(列"<<col<<"对宫"<<room(p[0],col)<<"的影响)。"<<endl;
node[i][j].semaphore[m]=0;
node[i][j].probable--;
if(node[i][j].probable==1)
call_subtraction(i,j,recall);//
a[i-k1]=1;
if(a[3]==0) a[3]=j;
else if(a[3]!=j) a[4]=j;
}
if(a[0]==1) row_technology(k1,m,recall);
if(a[1]==1) row_technology(k1+1,m,recall);
if(a[2]==1) row_technology(k1+2,m,recall);
if(a[3]!=0) col_technology(a[3],m,recall);
if(a[4]!=0) col_technology(a[4],m,recall);
delete[] a;
}
}
delete[] p;
}
void room_technology(int i,int m,int recall)//m只能填在某空上 或 k只能填在宫的某一行(列)上 , i表示room号,j=4表示遍历所有技巧,j=1表示此宫只有一个位置可填某候选数,j=2表示某候选数只能填在宫的某行,j=3表示某候选数只能填在某宫的某列
{
int k1=room(i)[0],k2=room(i)[1];
vector<int> v1;
vector<vector<int>> v3;
int sum=0;
for(int i=k1;i<=k1+2;i++)
for(int n=k2;n<=k2+2;n++)
if(node[i][n].semaphore[m]==1)
{
sum++;
v1.push_back(i);
v1.push_back(n);
v3.push_back(v1);
v1.clear();
}
if(sum==1)//非回溯
{
int* p=new int[10];//p[1]到p[9]如果为1说明会被减去
for(int i=1;i<=9;i++)
p[i]=0;
for(int k=1;k<=m-1;k++)
if(node[v3[0][0]][v3[0][1]].semaphore[k]==1)
{
p[k]=1;//此时不对要减去的候选数进行操作,把它后延是因为后面还有更诱人的subtraction操作,让它先进行则更快
out_stream<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<v3[0][1]<<"应删"<<k<<"(宫"<<i<<"只一格能填"<<m<<")。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<v3[0][1]<<"应删"<<k<<"(宫"<<i<<"只一格能填"<<m<<")。"<<endl;
}
for(int k=m+1;k<=9 ;k++)
if(node[v3[0][0]][v3[0][1]].semaphore[k]==1)
{
p[k]=1;//此时不对要减去的候选数进行操作,把它后延是因为后面还有更诱人的subtraction操作,让它先进行则更快
out_stream<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<v3[0][1]<<"应删"<<k<<"(宫"<<i<<"只一格能填"<<m<<")。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<v3[0][1]<<"应删"<<k<<"(宫"<<i<<"只一格能填"<<m<<")。"<<endl;
}
for(int k=1;k<=9;k++)
node[v3[0][0]][v3[0][1]].semaphore[k]=0;
node[v3[0][0]][v3[0][1]].probable=0;
node[v3[0][0]][v3[0][1]].semaphore[10]=m;
out_stream<<"唯一数:"<<char(v3[0][0]-1+'A')<<v3[0][1]<<"应填"<<m<<"。"<<endl;
cout<<"唯一数:"<<char(v3[0][0]-1+'A')<<v3[0][1]<<"应填"<<m<<"。"<<endl;
subtraction(v3[0][0],v3[0][1],m);
for(int k=1;k<=9;k++)
if(p[k]==1)
{
row_technology(v3[0][0],k,recall);
col_technology(v3[0][1],k,recall);
room_technology(room(v3[0][0],v3[0][1]),k,recall);
}
delete[] p;
}
else if(sum==2)//非回溯
{
if(v3[0][0]==v3[1][0])
{
int* p=new int[2];//存放它可能影响的两个宫
p[0]=0;p[1]=0;
for(int col=1;col<=k2-1;col++)
if(node[v3[0][0]][col].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
node[v3[0][0]][col].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[v3[0][0]][col].probable--;
if(node[v3[0][0]][col].probable==1)
call_subtraction(v3[0][0],col,recall);
col_technology(col,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(v3[0][0],col);
else if( p[0]!=room(v3[0][0],col)) p[1]=room(v3[0][0],col);
}
for(int col=k2+3;col<=9;col++)
if(node[v3[0][0]][col].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
node[v3[0][0]][col].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[v3[0][0]][col].probable--;
if(node[v3[0][0]][col].probable==1)
call_subtraction(v3[0][0],col,recall);
col_technology(col,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(v3[0][0],col);
else if( p[0]!=room(v3[0][0],col)) p[1]=room(v3[0][0],col);
}
if(p[0]!=0) room_technology(p[0],m,recall);//p[0]!=0说明room p[0]中的候选数v[i]被减掉至少一个,如果剪掉两个就应该把这个语句放在for循环外面
if(p[1]!=0) room_technology(p[1],m,recall);
delete[] p;
}
else if(v3[0][1]==v3[1][1])
{
int* p=new int[2];//存放它可能影响的两个宫
p[0]=0;p[1]=0;
for(int row=1;row<=k1-1;row++)
if(node[row][v3[0][1]].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
node[row][v3[0][1]].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[row][v3[0][1]].probable--;
if(node[row][v3[0][1]].probable==1)
call_subtraction(row,v3[0][1],recall);
row_technology(row,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(row,v3[0][1]);
else if( p[0]!=room(row,v3[0][1])) p[1]=room(row,v3[0][1]);
}
for(int row=k1+3;row<=9;row++)
if(node[row][v3[0][1]].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
node[row][v3[0][1]].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[row][v3[0][1]].probable--;
if(node[row][v3[0][1]].probable==1)
call_subtraction(row,v3[0][1],recall);
row_technology(row,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(row,v3[0][1]);
else if( p[0]!=room(row,v3[0][1])) p[1]=room(row,v3[0][1]);
}
if(p[0]!=0) room_technology(p[0],m,recall);//p[0]!=0说明room p[0]中的候选数v[i]被减掉至少一个,如果剪掉两个就应该把这个语句放在for循环外面
if(p[1]!=0) room_technology(p[1],m,recall);
delete[] p;
}
}
else if(sum==3)//非回溯
{
if(v3[0][0]==v3[1][0] && v3[0][0]==v3[2][0] )
{
int* p=new int[2];//存放它可能影响的两个宫
p[0]=0;p[1]=0;
for(int col=1;col<=k2-1;col++)
if(node[v3[0][0]][col].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
node[v3[0][0]][col].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[v3[0][0]][col].probable--;
if(node[v3[0][0]][col].probable==1)
call_subtraction(v3[0][0],col,recall);
col_technology(col,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(v3[0][0],col);
else if( p[0]!=room(v3[0][0],col)) p[1]=room(v3[0][0],col);
}
for(int col=k2+3;col<=9;col++)
if(node[v3[0][0]][col].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(v3[0][0]-1+'A')<<col<<"应删"<<m<<"(宫"<<i<<"对行"<<char(v3[0][0]-1+'A')<<"的影响)。"<<endl;
node[v3[0][0]][col].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[v3[0][0]][col].probable--;
if(node[v3[0][0]][col].probable==1)
call_subtraction(v3[0][0],col,recall);
col_technology(col,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(v3[0][0],col);
else if( p[0]!=room(v3[0][0],col)) p[1]=room(v3[0][0],col);
}
if(p[0]!=0) room_technology(p[0],m,recall);//p[0]!=0说明room p[0]中的候选数v[i]被减掉至少一个,如果剪掉两个就应该把这个语句放在for循环外面
if(p[1]!=0) room_technology(p[1],m,recall);
delete[] p;
}
else if(v3[0][1]==v3[1][1] && v3[0][1]==v3[2][1])
{
int* p=new int[2];//存放它可能影响的两个宫
p[0]=0;p[1]=0;
for(int row=1;row<=k1-1;row++)
if(node[row][v3[0][1]].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
node[row][v3[0][1]].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[row][v3[0][1]].probable--;
if(node[row][v3[0][1]].probable==1)
call_subtraction(row,v3[0][1],recall);
row_technology(row,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(row,v3[0][1]);
else if( p[0]!=room(row,v3[0][1])) p[1]=room(row,v3[0][1]);
}
for(int row=k1+3;row<=9;row++)
if(node[row][v3[0][1]].semaphore[m]==1)
{
out_stream<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
cout<<"行列区互相影响候选数删减法:"<<char(row-1+'A')<<v3[0][1]<<"应删"<<m<<"(宫"<<i<<"对列"<<v3[0][1]<<"的影响)。"<<endl;
node[row][v3[0][1]].semaphore[m]=0;//非回溯,技巧是(区块影响行列)候选数删减法
node[row][v3[0][1]].probable--;
if(node[row][v3[0][1]].probable==1)
call_subtraction(row,v3[0][1],recall);
row_technology(row,m,recall);//这里的调用可以迅速缩短得到结果时间,不管是正确还是错误
if(p[0]==0) p[0]=room(row,v3[0][1]);
else if( p[0]!=room(row,v3[0][1])) p[1]=room(row,v3[0][1]);
}
if(p[0]!=0) room_technology(p[0],m,recall);//p[0]!=0说明room p[0]中的候选数v[i]被减掉至少一个,如果剪掉两个就应该把这个语句放在for循环外面
if(p[1]!=0) room_technology(p[1],m,recall);
delete[] p;
}
}
v3.clear();
}
void row_technology(int row ,int recall)
{
vector<int> v;
int col;
int *p=new int[10];
for(col=1;col<=9;col++)
p[col]=0;
for( col=1;col<=9;col++)
if(node[row][col].semaphore[10]!=0)
p[node[row][col].semaphore[10]]=1;
for(col=1;col<=9;col++)
if(p[col]==0)
v.push_back(col);
delete[] p;
if(v.size()==0) goto loop;
for(int i=v.size()-1;i>=0;i--)
row_technology(row,v[i],recall);
v.clear();
loop: ;
}
void col_technology(int col,int recall)
{
vector<int> v;
int row;
int *p=new int[10];
for(row=1;row<=9;row++)
p[row]=0;
for( row=1;row<=9;row++)
if(node[row][col].semaphore[10]!=0)
p[node[row][col].semaphore[10]]=1;
for(row=1;row<=9;row++)
if(p[row]==0)
v.push_back(row);
delete[] p;
if(v.size()==0) goto loop;
for(int i=v.size()-1;i>=0;i--)
col_technology(col,v[i],recall);
v.clear();
loop: ;
}
void room_technology(int i,int recall)
{
int k1=room(i)[0],k2=room(i)[1];
vector<int> v;
int m;
int *p=new int[10];
for(m=1;m<=9;m++)
p[m]=0;
for( m=k1;m<=k1+2;m++)
for(int n=k2;n<=k2+2;n++)
if(node[m][n].semaphore[10]!=0)
p[node[m][n].semaphore[10]]=1;
for(m=1;m<=9;m++)
if(p[m]==0)
v.push_back(m);
delete[] p;
if(v.size()==0) goto loop;
for( m=v.size()-1;m>=0;m--)
room_technology(i,v[m],recall);
v.clear();
loop: ;
}
int count_candidate_number()
{
int sum=0;
for(int row=1;row<=9;row++)
for(int col=1;col<=9;col++)
if(node[row][col].probable==0) continue;
else
{
for(int k=1;k<=9;k++)
if(node[row][col].semaphore[k]==1) sum++;
}
return (sum);
}
bool row_col_room_technology_solve()
{
int j;
do{
j=count_candidate_number();
for(int i=1;i<=9;i++)
{
row_technology(i,0);
col_technology(i,0);
room_technology(i,0);
}
}while(j!=count_candidate_number());
if(count_candidate_number())
return (false);
else return (true);
}
void print_all()
{
out_stream<<"print storage"<<endl;
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
out_stream<<node[i][j].semaphore[10]<<" ";
if(j%3==0) out_stream<<" ";
}
out_stream<<endl;
if(i%3==0) out_stream<<endl;
}
out_stream<<endl<<endl;
}
int test()
{
int sum=0,i,j;
for(int i=1;i<=9;i++)
{
sum=0;
for(int j=1;j<=9;j++)
sum+=node[i][j].semaphore[10];
if(sum!=45) {cout<<"wrong"<<endl; return 0;}
}
for( j=1;j<=9;j++)
{
sum=0;
for(i=1;i<=9;i++)
sum+=node[i][j].semaphore[10];
if(sum!=45) {cout<<"wrong"<<endl; return 0;}
}
for(int i=1;i<=9;i++)
{
sum=0;
int row=(i-1)/3*3+1;
int col=(i-1)%3*3+1;
for(int m=row;m<=row+2;m++)
for(int n=col;n<=col+2;n++)
sum+=node[m][n].semaphore[10];
if(sum!=45) {cout<<"wrong"<<endl; return 0;}
}
return 1;
}
bool fun( int array[10])
{
int i,j;
for(i=1;i<=8;i++)
{
if(*(array+i)==0) continue;
for(j=i+1;j<=9;j++)
if(*(array+i)==*(array+j)) return (false);
}
return (true);
}
void add(int row,int col,int storage,int semaphore,vector<int> must_add1,vector<int> must_add2)//semaphore的值为100,200,300,400 表示从四个方向上恢复
{
if(semaphore==2)
{
finished--;
node[row][col].semaphore[storage]=1;
node[row][col].probable+=1; //node[row][col].storage的值最后变回0,下面恢复三个区域要用到这个值。
node[row][col].semaphore[10]=0;
for(int i=(must_add1.size()==0)? 1:(must_add1.size()-1)/2+1; i<=(must_add2.size()-1)/2; i++)
{
if(node[must_add2[2*i-2]][must_add2[2*i-1]].semaphore[storage]==0)
{
node[must_add2[2*i-2]][must_add2[2*i-1]].semaphore[storage]=1;
node[must_add2[2*i-2]][must_add2[2*i-1]].probable++;
}
}
if(node[row][col].probable_explore_recover!=0)
{
for(int i=1;i<=9;i++)
node[row][col].semaphore[i]=node[row][col].semaphore_explore_recover[i];
node[row][col].probable=node[row][col].probable_explore_recover;
for(int i=1;i<=9;i++)
node[row][col].semaphore_explore_recover[i]=0;
node[row][col].probable_explore_recover=0;
min_probable_node.row=row;
min_probable_node.col=col;
min_probable_node.probable=node[row][col].probable;
}
}
else if(semaphore==3)
{ //这个条件表达式是调试后发现的
for(int i=(must_add1.size()==0)? 1:(must_add1.size()-1)/2+1; i<=(must_add2.size()-1)/2; i++)
{
if(node[must_add2[2*i-2]][must_add2[2*i-1]].semaphore[storage]==0)
{
node[must_add2[2*i-2]][must_add2[2*i-1]].semaphore[storage]=1;
node[must_add2[2*i-2]][must_add2[2*i-1]].probable++;
}
}
}
}
int find_partner(vector<int> v1)
{
int i=0;
while(i++<=v2.size()-1)//i++要注意用好
{
if(v2[i-1].size()%2==1) continue;//调试后加的排除选中must_add的情况,
if(v2[i-1][0]==v1[0] && v2[i-1][1]==v1[1] )
return(i-1);
}
}
void addv2(vector<vector<int>> &v2)
{
vector<vector<int>> v2_transcript;
v2_transcript.push_back(v2[v2.size()-1]);
v2_transcript.push_back(v2[v2.size()-2]);
v2.pop_back();
v2.pop_back();
for(int i=v2.size()-1;i>=0;i--)
{
if(v2_transcript[0][3]==400 && v2[i][3]==400)
{
int index=find_partner(v2_transcript[0]);
add(v2_transcript[0][0],v2_transcript[0][1],v2[index][2],3,v2[index+1],v2_transcript[1]);
v2_transcript.pop_back();
v2_transcript.pop_back();
v2_transcript.push_back(v2[i]);
v2_transcript.push_back(v2[i-1]);
v2.pop_back();
v2.pop_back();
i--;
continue;
}
else if(v2_transcript[0][3]==400 && v2[i][3]!=400 && v2.size()>1)
{
add(v2[i][0],v2[i][1],v2[i][2],2,v1,v2_transcript[1]);
v2_transcript.pop_back();
v2_transcript.pop_back();
v2_transcript.push_back(v2[i]);
v2_transcript.push_back(v2[i-1]);
v2.pop_back();
v2.pop_back();
i--;
continue;
}
else if(v2_transcript[0][3]!=400 && v2[i][3]!=400 && v2.size()>1)
{
add(v2[i][0],v2[i][1],v2[i][2],2,v1,v2_transcript[1]);
v2_transcript.pop_back();
v2_transcript.pop_back();
v2_transcript.push_back(v2[i]);
v2_transcript.push_back(v2[i-1]);
v2.pop_back();
v2.pop_back();
i--;
continue;
}
else if(v2_transcript[0][3]!=400 && v2[i][3]==400 )
{
int index=find_partner(v2[i]);
int index_call=index;
while(v2[index_call-2][3]==400)//调试后发现的错误,原来以为index求一次就够v2[index-2]就一定是调用了v2_transcript[0]
{
index_call=find_partner(v2[index_call-2]);
}
add(v2[index_call-2][0],v2[index_call-2][1],v2[index_call-2][2],3,v2[index-1],v2_transcript[1]);
v2_transcript.pop_back();
v2_transcript.pop_back();
v2_transcript.push_back(v2[i]);
v2_transcript.push_back(v2[i-1]);
v2.pop_back();
v2.pop_back();
i--;
continue;
}
else if(v2_transcript[0][3]==400 && v2[i][3]!=400 && v2.size()==1)
{
add(v2[i][0],v2[i][1],v2[i][2],2,v1,v2_transcript[1]);
v2_transcript.pop_back();
v2_transcript.pop_back();
v2.pop_back();
break;
}
else if(v2_transcript[0][3]!=400 && v2[i][3]!=400 && v2.size()==1)
{
add(v2[i][0],v2[i][1],v2[i][2],2,v1,v2_transcript[1]);
v2_transcript.pop_back();
v2_transcript.pop_back();
v2.pop_back();
break;
}
}
}
void copy(vector<vector<int>> vec)
{
for(int i=0;i<=vec.size()-1;i++)
v2.push_back(vec[i]);
}
void explore( )
{
int row,col,probable;
probable=10;
for(int i=9;i>=1;i--)
{
for(int j=9 ;j>=1;j--)
{
if(probable>=node[i][j].probable && node[i][j].probable!=0 )
{ probable=node[i][j].probable;
row=i;
col=j;
}
}
}
min_probable_node.row=row;
min_probable_node.col=col;
min_probable_node.probable=probable;
count++;
for(int k=1;k<=9;k++)
{
if(node[min_probable_node.row][min_probable_node.col].semaphore[k]==1)
{
for(int r=1;r<=9;r++)
if(node[min_probable_node.row][r].semaphore[10]==k )
goto loop;
for(int r=1;r<=9;r++)
if(node[r][min_probable_node.col].semaphore[10]==k )
goto loop;
switch(room(min_probable_node.row,min_probable_node.col))
{
case 1: for( int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 2: for( int i=1;i<=3;i++)
for(int j=4;j<=6;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 3: for( int i=1;i<=3;i++)
for(int j=7;j<=9;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 4: for( int i=4;i<=6;i++)
for(int j=1;j<=3;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 5: for( int i=4;i<=6;i++)
for(int j=4;j<=6;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 6: for( int i=4;i<=6;i++)
for(int j=7;j<=9;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 7: for( int i=7;i<=9;i++)
for(int j=1;j<=3;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 8: for( int i=7;i<=9;i++)
for(int j=4;j<=6;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
case 9: for( int i=7;i<=9;i++)
for(int j=7;j<=9;j++)
{
if(node[i][j].semaphore[10]==k)
goto loop;
} break;
}
for(int r=1;r<=9;r++)
node[min_probable_node.row][min_probable_node.col].semaphore_explore_recover[r]=node[min_probable_node.row][min_probable_node.col].semaphore[r];
node[min_probable_node.row][min_probable_node.col].probable_explore_recover=node[min_probable_node.row][min_probable_node.col].probable;
for(int r=1;r<=9;r++)
node[min_probable_node.row][min_probable_node.col].semaphore[r]=0;
node[min_probable_node.row][min_probable_node.col].probable=0;
node[min_probable_node.row][min_probable_node.col].semaphore[10]=k;
v1.push_back(min_probable_node.row);
v1.push_back(min_probable_node.col);
v1.push_back(node[min_probable_node.row][min_probable_node.col].semaphore[10]);
v1.push_back(0);
v2.push_back(v1);
v1.clear();
node[min_probable_node.row][min_probable_node.col].explore[k]=1;
//print_all(1);//
if(subtraction(min_probable_node.row,min_probable_node.col)==success)
;
else if(v2[v2.size()-1][3]>30 && v2[v2.size()-1][3]!=400)
{
addv2(v2);
v2.clear();
node[min_probable_node.row][min_probable_node.col].explore[k]=0;
}
else
{
v3.push_back(v2);
v2.clear();
explore();
}
}
loop: ;
}
int sum=0;
for(int k=1;k<=9;k++)
sum+=node[min_probable_node.row][min_probable_node.col].explore[k];
if(sum==0)
{
node[v3[v3.size()-1][0][0]][v3[v3.size()-1][0][1]].explore[v3[v3.size()-1][0][2]]=0;
copy(v3[v3.size()-1]); //调试后加的。
addv2(v2);
v3.pop_back();
}
}
int main()
{
int information_number=0;
long time;
char char_start[82];
int int_start[82];
ifstream cin_stream;
cin_stream.open("d:\\my documents\\visual studio 2010\\projects\\测试算法\\fenlan.txt");
cin_stream>>char_start;
for(int i=1;i<82;i++)
int_start[i]=char_start[i-1]-'0';
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]);
v2.push_back(v1);
v1.clear();
}
}
information_number=v2.size();
cin_stream.close();
out_stream.open("d:\\my documents\\visual studio 2010\\projects\\测试算法\\2.txt");
time=clock();
fills_up();
for(int i=0;i<information_number;i++)
{
for(int k=1;k<=9;k++)
node[v2[i][0]][v2[i][1]].semaphore[k]=0;
node[v2[i][0]][v2[i][1]].probable=0;
node[v2[i][0]][v2[i][1]].semaphore[10]=v2[i][2];
}
print_all();//这里是输出题目,看看自己的输入是否有误
vector<vector<int>> v2_temporary;
for(int i=0;i<information_number;i++)
{
v2_temporary=subtraction(v2[i][0],v2[i][1]);
if(v2_temporary==success)
break;
if(v2_temporary[v2.size()-1][3]==400) continue;
if(v2_temporary[v2.size()-1][3]==100 || v2_temporary[v2.size()-1][3]==200 ||v2_temporary[v2.size()-1][3]==300)
{
cout<<"数组题目设计错误"<<endl;
}
}
v2.clear();
print_all();//这里是不用技巧时得到的解题结果
if(finished==81)
{
print_all();
out_stream<<endl;
if(test()) {time=clock()-time; out_stream<<"用时(不含输入数据时间)"<<time/1000<<"秒"<<time%1000<<"毫秒"<<endl; cout<<"right"<<endl;}
system("pause");
return 0;
}
row_col_room_technology_solve();
print_all();
explore();
if(test())
{
print_all();
out_stream<<endl;
time=clock()-time;
out_stream<<"用时(不含输入数据时间)"<<time/1000<<"秒"<<time%1000<<"毫秒"<<endl;
cout<<"用时(不含输入数据时间)"<<time/1000<<"秒"<<time%1000<<"毫秒"<<endl;
cout<<"right"<<endl;
}
out_stream.close();
system("pause");
}