深搜+剪枝--poj2676--数独

 题干描述  就是一个数独问题

这道题说是简单题,但是我觉得这个“简单”是在对数据结构,递归非常熟悉的基础上,对于我这种新手其实并不简单,也有很多坑等我我去踩

这道题说是剪枝,但是我觉得主要妙点还是好在gw老师的设置的数据结构太好了。见代码。

当要在一个空格子(0)放数字时,直接放那些在这个空格子所在行、列、3*3小方框没出现过的数字,这样效率不就高了许多吗?

但是,找到这些已经出现过的数字呢?记录下来?或者搜索一下?dwd

gw老师的办法很棒,这里面有一个重要的启发是:当题目要频繁查找某个位置的元素的状态,例如本题中我们要频繁的查找某位置其所在行、列、3*3小方框是否包含某数字,这时就可以用位置做数组下标,用值记录状态(0,1),这样直接访问数组就获得了所需信息,不必查找。

从这一题我认识到,我对递归的过程仍然不熟悉,特别是回溯,但是不能浮躁,不能气馁,慢慢来~

ac代码:

#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
#define maxn 102

int hn[10][10];  //记录,某行中是否存有某个数 
int ln[10][10];
int gn[10][10];

int map[10][10];  //地图 

struct pos{
    int r,c;
    pos(int rr,int cc):r(rr),c(cc){}
};

vector<pos> b;

inline int gb(int r,int c){       //由行列号得到序号(1~81) 
    int rr=r/3;
    int cc=c/3;
    return rr*3+cc;
}

void saf(int i,int j,int num,int f){      //第f=1-->i行j列有num这个数,f=0意思相反 
    hn[i][num]=f;
    ln[j][num]=f;
    gn[gb(i,j)][num]=f;
}

bool isk(int i,int j,int num){            //num这个数放在i,j位置ok吗? 
    return !gn[gb(i,j)][num] && !hn[i][num]  && !ln[j][num]; 
}

int dfs(int n){
    if(n<0) return 1;               //从80->0 当n=-1代表前面0-80全部处理过 
    int r=b[n].r;
    int c=b[n].c;
    for(int i=1;i<=9;++i){
        if(isk(r,c,i)){
            map[r][c]=i;
            saf(r,c,i,1);
            if(dfs(n-1))
            return 1;
            else
            saf(r,c,i,0);           //回溯 
        }
    }
    return 0;
}

int main()
{
    freopen("in.txt","r",stdin);
    int t;
    cin>>t;
    while(t--){
        memset(hn,0,sizeof(hn));
        memset(ln,0,sizeof(ln));
        memset(gn,0,sizeof(gn));
        b.clear();
        for(int i=0;i<9;i++)
        for(int j=0;j<9;j++){
            char c;
            cin>>c;
            map[i][j]=c-'0';
            if(map[i][j])
            saf(i,j,map[i][j],1);
            else
            b.push_back(pos(i,j));
        }
        if(dfs(b.size()-1)){
            for(int i=0;i<9;i++){
                for(int j=0;j<9;j++)
                cout<<char(map[i][j]+'0');
                cout<<endl;
            }
        }    
    }
    return 0;
}
柳暗花明又一村
原文地址:https://www.cnblogs.com/ucandoit/p/8530303.html