ACM第二次练习—1026

题意:自从2006年3月10日至11日的首届数独世界锦标赛以后,数独这项游戏越来越受到人们的喜爱和重视。<br>据说,在2008北京奥运会上,会将数独列为一个单独的项目进行比赛,冠军将有可能获得的一份巨大的奖品———HDU免费七日游外加lcy亲笔签名以及同hdu acm team合影留念的机会。<br>所以全球人民前仆后继,为了奖品日夜训练茶饭不思。当然也包括初学者linle,不过他太笨了又没有多少耐性,只能做做最最基本的数独题,不过他还是想得到那些奖品,你能帮帮他吗?你只要把答案告诉他就可以,不用教他是怎么做的。<br><br>数独游戏的规则是这样的:在一个9x9的方格中,你需要把数字1-9填写到空格当中,并且使方格的每一行和每一列中都包含1-9这九个数字。同时还要保证,空格中用粗线划分成9个3x3的方格也同时包含1-9这九个数字。比如有这样一个题,大家可以仔细观察一下,在这里面每行、每列,以及每个3x3的方格都包含1-9这九个数字。

思路:遇到的第一个难题:如何在dfs中找到问号的位置 难道一遍一遍的查找???答案:在主函数中记录所有问号的位置第二个难题  一行中有多个问号  那怎么做出这几个数的全排列 让其去dfs答案 不用这样直接在问号处 填写1-9的数字看是否可行第三个难题如何保证只有一个正确答案答案  自己错误理解了题意 对于每组测试数据保证它有且只有一个解 是指只要找到了一个解就不需要再继续寻找其他解了第4个难题超时了答案如果没有EOF会 一些小的剪枝和技巧也能解决问题1由于要求先输入一个数我一开始先输入1个数  然后在输入第一行中的数(第一个由于已经输入所以不包括)   再然后输入2--9行的数 这样很复杂也浪费时间代码中的方法很给力  先输入一个数 然后在全部遍历 已经输入过的 直接continue 不用再输入     不这样 会超时2  由于分成多个小方块   分成了多个9宫格  输入数据时 如果按数组从1-9输入没有明显的规律不好找出 对于一个x y其位于哪个9宫格 而如果从0-8 输入  xx = x/3*3; yy = y/3*3;     //则很容易按照这个方法计算属于哪个9宫格 xxx = xx+3; yyy = yy+3;  3 千千万万搞清楚2组解之间有一行空格的含义4这里的输入最好用%s  因为%s 遇到空格或回车就终止了 不会把空格回车符存进去  而用%c  还得在后面加个getchar()虽然这样也行 但是复杂  况且 这样能够造成超时  我试过了这样能够造成超时 所以遇到能简化的地方尽量简化。

感想:自己做不出来,只好参考别人的。

代码:

#include<iostream>  
#include<cstdio>  
#include<cstdlib>  
#include<cstring>  
#include<string>  
#include<queue>  
#include<algorithm>  
#include<map>  
#include<iomanip>  
#define INF 99999999  
using namespace std;  
  
const int MAX=10;  
char map_[MAX][MAX];  
int pos[MAX*9][2];//存储是问号点的座标,方便搜索时只需要搜索这些点填什么数字.  
bool row[MAX][MAX],list[MAX][MAX];//用来标明哪行哪列出现过什么数.  
int k;  
  
bool check(int v,int num){  
    int n=pos[v][0]/3*3;//搜索周围9小格的行的开始搜索位置.  
    int m=pos[v][1]/3*3;//搜索周围9小格的列的开始搜索位置.  
    for(int i=n;i<n+3;++i){  
        for(int j=m;j<m+3;++j){  
            if(map_[i][j] == num+'0')return false;  
        }  
    }  
    return true;  
}  
  
bool DFS(int v){  
    if(v == k){return true;}//代表前面已经把所有的点都搜索完了.  
    for(int i=1;i<10;++i){  
        if(!row[pos[v][0]][i] && !list[pos[v][1]][i] && check(v,i)){  
            map_[pos[v][0]][pos[v][1]]=i+'0';  
            row[pos[v][0]][i]=true;  
            list[pos[v][1]][i]=true;  
            if(DFS(v+1)){return true;}  
            map_[pos[v][0]][pos[v][1]]='?';  
            row[pos[v][0]][i]=false;  
            list[pos[v][1]][i]=false;  
        }  
    }  
    return false;  
}  
  
void output(){  
    for(int i=0;i<9;++i){  
        cout<<map_[i][0];  
        for(int j=1;j<9;++j){  
            cout<<' '<<map_[i][j];  
        }  
        cout<<endl;  
    }  
    return;  
}  
  
int main(){  
 int num=0;  
    while(1){  
     k=0;  
     memset(row,false,sizeof row);  
     memset(list,false,sizeof list);  
     for(int i=0;i<9;++i){  
          for(int j=0;j<9;++j){  
              if(!(cin>>map_[i][j]))exit(0);  
              if(map_[i][j] == '?'){pos[k][0]=i;pos[k++][1]=j;continue;}  
              row[i][map_[i][j]-'0']=true;  
              list[j][map_[i][j]-'0']=true;  
            }  
        }  
     DFS(0);//开始搜索第1个是问号的点.  
     if(num++)cout<<endl;  
     output();  
    }  
    return 0;  
}   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章