hdu - 数独问题

警告:  qdu14级信安同学请不要复制此代码,要不然会被查重……


E - 数独问题
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit  Status

Description

自从2006年3月10日至11日的首届数独世界锦标赛以后,数独这项游戏越来越受到人们的喜爱和重视。 
据说,在2008北京奥运会上,会将数独列为一个单独的项目进行比赛,冠军将有可能获得的一份巨大的奖品―――HDU免费七日游外加lcy亲笔签名以及同hdu acm team合影留念的机会。 
所以全球人民前仆后继,为了奖品日夜训练茶饭不思。当然也包括初学者linle,不过他太笨了又没有多少耐性,只能做做最最基本的数独题,不过他还是想得到那些奖品,你能帮帮他吗?你只要把答案告诉他就可以,不用教他是怎么做的。 

数独游戏的规则是这样的:在一个9x9的方格中,你需要把数字1-9填写到空格当中,并且使方格的每一行和每一列中都包含1-9这九个数字。同时还要保证,空格中用粗线划分成9个3x3的方格也同时包含1-9这九个数字。比如有这样一个题,大家可以仔细观察一下,在这里面每行、每列,以及每个3x3的方格都包含1-9这九个数字。 

例题: 
 

答案: 
 

Input

本题包含多组测试,每组之间由一个空行隔开。每组测试会给你一个 9*9 的矩阵,同一行相邻的两个元素用一个空格分开。其中1-9代表该位置的已经填好的数,问号(?)表示需要你填的数。 

Output

对于每组测试,请输出它的解,同一行相邻的两个数用一个空格分开。两组解之间要一个空行。 
对于每组测试数据保证它有且只有一个解。 

Sample Input

7 1 2 ? 6 ? 3 5 8
? 6 5 2 ? 7 1 ? 4
? ? 8 5 1 3 6 7 2
9 2 4 ? 5 6 ? 3 7
5 ? 6 ? ? ? 2 4 1
1 ? 3 7 2 ? 9 ? 5
? ? 1 9 7 5 4 8 6
6 ? 7 8 3 ? 5 1 9
8 5 9 ? 4 ? ? 2 3

Sample Output

7 1 2 4 6 9 3 5 8
3 6 5 2 8 7 1 9 4
4 9 8 5 1 3 6 7 2
9 2 4 1 5 6 8 3 7
5 7 6 3 9 8 2 4 1
1 8 3 7 2 4 9 6 5
2 3 1 9 7 5 4 8 6
6 4 7 8 3 2 5 1 9
8 5 9 6 4 1 7 2 3

做此题真是肝肠寸断……


首先此题应该用  搜索  来做。

初步构想,通过划分的9个小方格,将每个小方格内带?的地方的可能值列出来,存在vector里,这样搜索的时候只需判断行或者列是否满足规则就可。

然后我就开始搜点了,一个一个搜,结果没做出来……(好笨……)

然后百度了一波大神的,发现他们都是直接搜带?的点,恍然大悟。于是修改代码,加了结构体。

历尽千辛万苦,终于做出答案来了,赶紧提交,超时了……

看到大神写的注意事项,原来用while(1)  会超时,于是改成while(~scanf) ,瞥了一眼大神的就自己改,发现输入直接不对,当时用的str[10] ,和 %s 直接挂了,才看见输入中间有空格,只好仔细研究大神的输入,发现用的str[2],在str[0]取数,空格存在str[1]里 ,极妙的做法,活到老,学到老。

改过来提交,还是超时……好气呀!!!!!

找不出猫饼了……只有用vector存的值,和AC代码不同(直接枚举1到9),没办法,我也改成直接枚举1到9,然后过了。不过还是想不通为什么用vector存可能值会超时……




代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef struct WH{    ///用结构体存储 ? 的坐标
    int x;
    int y;
}wh;
int a[15][15];     ///数独面板
int f[15];
int tm = 1;        ///带?的个数+1
vector v[15];
int flag = 0;      ///结束标志
wh q[100];          ///  '?' 节点存储
int getfg(int x,int y){  ///获取坐标所在的3X3方格位置
    return ((x-1)/3)*3+((y-1)/3+1);
}
int getzb(int t){
    int xx=(t)/3*3+1;
    int yy=(t+1)%3-1;
    printf("%d %d\n",xx,yy);
    return 0;
}
bool isok9(int x,int y,int ans){   ///3X3小方格或行或列符合规则吗
    for(int i = 1; i <= 9; ++i)
        if(a[i][y] == ans)
            return false;
    for(int i = 1; i <= 9; ++i)
        if(a[x][i] == ans)
            return false;
    //int tmp = getfg(x,y);
    int xx=(x-1)/3*3+1;
    int yy=(y-1)/3*3+1;

    for(int i = xx; i < xx+3; ++i){
        for(int j = yy; j < yy+3; ++j){
            if(a[i][j] == ans) return false;
        }
    }
    return true;
}
void print(){                     ///打印结果
    for(int i = 1; i <= 9; ++i){
        printf("%d",a[i][1]);
        for(int j = 2; j <= 9; ++j){
            printf(" %d",a[i][j]);
        }
        printf("\n");
    }
    //printf("\n");
}
void printv(){
    for(int i = 1; i <= 9; ++i){
        printf("%d:  ",i);
        for(int j = 0; j < (int)v[i].size(); ++j){
            printf("%d ",v[i].at(j));
        }
        printf("\n");
    }
}
void printwh(){
    for(int i = 1; i < tm; ++i){
        printf("%d %d : %d\n",q[i].x,q[i].y,getfg(q[i].x,q[i].y));
    }
}

void dfs(int t){
    if(t == tm){    ///搜到最后一个点结束
        flag = 1;
        return;
    }
    int x = q[t].x;
    int y = q[t].y;

    //for(int i = 0; i < (int)v[tmp].size(); ++i){
    for(int i = 1; i <= 9; ++i){
        if(isok9(x,y,i)){
            a[x][y] = i;
            dfs(t+1);
            if(flag) return;
            a[x][y] = 0;
        }
    }
}
int main(int argc, char *argv[]) {
    int k = 1;
    char str[2];
    while(~scanf("%s",str)){
        getchar();
        tm = 1;
        flag = 0;
        //memset(book,0,sizeof(book));
        memset(f,0,sizeof(f));
        for(int i = 1; i <= 9; ++i) v[i].clear();
        if(str[0] != '?') a[1][1] = str[0] - '0';
        else{
            q[tm].x = 1;
            q[tm++].y = 1;
            a[1][1] = 0;
        }
        for(int i = 1; i <= 9; ++i){
            for(int j = 1; j <= 9; ++j){
                if(i == 1 && j == 1) continue;
                scanf("%s",str);
                if(str[0] != '?') a[i][j] = (str[0]-'0');
                else{
                    q[tm].x = i;
                    q[tm++].y = j;
                    a[i][j] = 0;
                }
            }
        }
        for(int i = 1; i <= 9; i += 3){
            for(int j = 1; j <= 9; j += 3){
                memset(f,0,sizeof(f));
                for(int k = i; k < i+3; ++k){
                    for(int l = j; l < j+3; ++l){
                        f[a[k][l]] = 1;
                    }
                }
                int t = getfg(i,j);
                for(int k1 = 1; k1 <= 9; ++k1)
                    if(f[k1] == 0) v[t].push_back(k1);
            }
        }
        dfs(1);
        if(k == 1){
            print();
            k++;
        }
        else{
            printf("\n");
            print();
        }
    }
	return 0;
}





你可能感兴趣的:(搜索,算法,算法,搜索)