搜索依旧写的稀烂。。
题目概述
链接:https://vjudge.net/problem/POJ-2676
大概就是数独吧。。横、数、小九宫格内不重复。
思路分析
这种题主要的手法还是搜索、暴力枚举。这道题主要的难点是以什么为单位开始搜(其实也不难)以及怎么设置vis剪枝。
在这里,我选择了以搜索二叉树构建的map来记录vis(毕竟map查找起来较容易)。将9个小九宫格、每行、每列各构建一个map来记录,所以需要map数组。然后,按照从左到右,从上到下的顺序,以格子为单位开始搜索。每次遍历1到9,检查是否符合条件,遇到不行就回溯。大概就是这样了。。
完整代码
#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <ctime>
using namespace std;
char floor[10][10]={0};
char floor_b[10][10]={0};
map<char,int> hang[10];
map<char,int> lie[10];
map<char,int> ge[10];
int flag=0;
inline int cnt_ge(int x,int y)//坐标->格子
{
if(x<3)
{
if(y<3) return 0;
else if(y<6) return 1;
else if(y<9) return 2;
}
else if(x<6)
{
if(y<3) return 3;
else if(y<6) return 4;
else if(y<9) return 5;
}
else if(x<9)
{
if(y<3) return 6;
else if(y<6) return 7;
else if(y<9) return 8;
}
}
inline bool judge(int x,int y,int i)
{
if(hang[x][i+'0']==0&&lie[y][i+'0']==0&&ge[cnt_ge(x,y)][i+'0']==0) return 1;
else return 0;
}
void dfs(int x,int y)
{
if(x==0&&y==9&&flag==0)
{
flag=1;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(floor[i][j]=='0')
{
printf("%c",floor_b[i][j]);
}
else printf("%c",floor[i][j]);
}
printf("\n");
}
}
else if(flag==0&&floor[x][y]!='0')
{
if(x==8) dfs(0,y+1);
else dfs(x+1,y);
}
else
{
for(int i=1;flag==0&&i<=9;i++)
{
if(judge(x,y,i))
{
floor_b[x][y]=i+'0';
hang[x][i+'0']=1;
lie[y][i+'0']=1;
ge[cnt_ge(x,y)][i+'0']=1;
if(x==8) dfs(0,y+1);
else dfs(x+1,y);
hang[x][i+'0']=0;
lie[y][i+'0']=0;
ge[cnt_ge(x,y)][i+'0']=0;
floor_b[x][y]='0';
}
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
flag=0;
for(int i=0;i<9;i++)
{
hang[i].clear();
lie[i].clear();
ge[i].clear();
}
memset(floor,'0',sizeof(floor));
memset(floor_b,'0',sizeof(floor_b));
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
cin>>floor[i][j];
if(floor[i][j]!='0')
{
hang[i][floor[i][j]]=1;
lie[j][floor[i][j]]=1;
ge[cnt_ge(i,j)][floor[i][j]]=1;
}
}
}
// clock_t startTime=clock();
dfs(0,0);
// clock_t endTime=clock();
// cout<<"用时:"<<(double)(endTime-startTime)/CLOCKS_PER_SEC<<"s"<<endl;
}
return 0;
}