poj 2676 dfs/DLX(数独)

题意:数独游戏,用零代表空格。

思路:从第一个空格开始深搜,遇到解便输出并退出。

版本1:直接深搜,每次尝试解时逐行,逐列,逐块判断该解是否成立。费时间比较多。

版本2:开三个二维数组记录第i行(列、块)是否已经填入了数字j,则每次判断只需按照数组值来进行判断即可。所需时间比版本1要好。

版本3:用DLX则0ms刷过~

输入:

1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107

输出:

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127

#include <stdio.h>
char in[10][10];
int s[10][10];
int T;
void print(){
	int i,j;
	for(i = 0;i<9;i++){
		for(j = 0;j<9;j++)
			printf("%d",s[i][j]);
		putchar('\n');
	}
}
int check(int x,int y,int num){//判断在x行y列处填入num是否合法
	int i,j;
	for(i = 0;i<9;i++)
		if(s[x][i]==num || s[i][y]==num)
			return 0;
	for(i = x/3*3;i<3+x/3*3;i++)
		for(j = y/3*3;j<3+y/3*3;j++)
			if(s[i][j] == num)
				return 0;
	return 1;
}
int dfs(int index){
	int i,x,y;
	if(index == 81){//表示得到解,输出
		print();
		return 1;
	}
	x = index/9;
	y = index%9;
	if(s[x][y])//如果此位置初始填入了数字,直接搜下一位置
		return dfs(index+1);
	else{
		for(i = 1;i<=9;i++)
			if(check(x,y,i)){
				s[x][y] = i;
				if(dfs(index+1))
					return 1;
			}
		s[x][y] = 0;//此位置尝试遍都无解,务必将此位置归零
	}
	return 0;
}
int main(){
	freopen("a.txt","r",stdin);
	scanf("%d",&T);
	while(T--){
		int i,j;
		getchar();
		for(i = 0;i<9;i++)
			scanf("%s",in[i]);
		for(i = 0;i<9;i++)
			for(j = 0;j<9;j++)
				s[i][j] = in[i][j]-'0';
		dfs(0);
	}
}

版本2:

#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
int s[10][10],blank[81][2],num;
int r[9][10],c[9][10],b[9][10];
int T;
int block(int i,int j){
    return i/3*3 + j/3;
}
void setflag(int i,int j,int x,int yn){
    r[i][x] = yn;
    c[j][x] = yn;
    b[block(i,j)][x] = yn;
}
int check(int x,int y,int w){
    return !r[x][w] && !c[y][w] && !b[block(x, y)][w];
}
int dfs(int d){
    int x,y,i;
    x = blank[d][0];
    y = blank[d][1];
    if(d==num)
        return 1;
    for(i = 1;i<=9;i++)
        if(check(x,y,i)){
            s[x][y] = i;
            setflag(x, y, i, 1);
            if(dfs(d+1))
                return 1;
            setflag(x, y, i, 0);
        }
    return 0;
}
int main(){
    scanf("%d",&T);
    while(T--){
        int i,j;
        char ch;
        num = 0;
        memset(s, 0, sizeof(s));
        memset(r, 0, sizeof(r));
        memset(c, 0, sizeof(c));
        memset(b, 0, sizeof(b));
        for(i = 0;i<9;i++){
            getchar();
            for(j = 0;j<9;j++){
                ch = getchar();
                if(ch-'0'){
                    s[i][j] = ch-'0';
                    setflag(i,j,ch-'0',1);
                }else{
                    blank[num][0] = i;
                    blank[num++][1] = j;
                }
            }
        }
        dfs(0);
        for(i = 0;i<9;i++){
            for(j = 0;j<9;j++)
                printf("%d",s[i][j]);
            putchar('\n');
        }
    }
    return 0;
}

DLX:

#include <cstdio>
#include <cstring>
#include <cmath>
#define L 9
#define N L*L*L
#define M L*L*4
#define OFFSET L*L
#define INF 0x3fffffff
using namespace std;
struct node{
    int l,r,u,d,t,x,y,c;
}p[N*4+M+5];
int cnt[M+5],top,T;
char tmp[L+5][L+5];
int res[L+2][L+2];
void init(){
    memset(cnt, 0, sizeof(cnt));
    for(int i = 0;i<=M;i++){
        p[i].l = i-1;
        p[i].r = i+1;
        p[i].u = p[i].d = p[i].c = i;
    }
    p[0].l = M;
    p[M].r = 0;
    top = M;
}
int block(int i,int j){
    int x = (int)sqrt((double)L);
    return (i-1)/x*x + (j-1)/x;
}
void add(int l,int x,int y,int t,int c){
    p[++top].x = x;
    p[top].y = y;
    p[top].t = t;
    p[top].l = l;
    p[p[top].l].r = top;
    p[top].u = p[c].u;
    p[p[top].u].d = top;
    p[c].u = top;
    p[top].d = p[top].c = c;
    cnt[c]++;
}
void addp(int i,int j,int k){
    add(top+4,i,j,k,(i-1)*L+j);
    add(top, i, j, k, OFFSET+(i-1)*L+k);
    add(top, i, j, k, OFFSET*2+(j-1)*L+k);
    add(top, i, j, k, OFFSET*3+block(i,j)*L+k);
}
void del(int c){
    int i,j;
    p[p[c].l].r = p[c].r;
    p[p[c].r].l = p[c].l;
    for(i = p[c].d;i!=c;i=p[i].d)
        for(j = p[i].r;j!=i;j=p[j].r){
            p[p[j].u].d = p[j].d;
            p[p[j].d].u = p[j].u;
            cnt[p[j].c]--;
        }
}
void re(int c){
    int i,j;
    p[p[c].l].r = c;
    p[p[c].r].l = c;
    for(i = p[c].d;i!=c;i=p[i].d)
        for(j = p[i].r;j!=i;j=p[j].r){
            p[p[j].u].d = j;
            p[p[j].d].u = j;
            cnt[p[j].c]++;
        }
}
int dfs(){
    int i,j,min = INF,c=0;
    if(!p[0].r)
        return 1;
    for(i = p[0].r;i;i=p[i].r)
        if(cnt[i] < min){
            min = cnt[i];
            c = i;
        }
    del(c);
    for(i = p[c].d;i!=c;i=p[i].d){
        res[p[i].x][p[i].y] = p[i].t;
        for(j = p[i].r;j!=i;j=p[j].r)
            del(p[j].c);
        if(dfs())
            return 1;
        for(j = p[i].l;j!=i;j=p[j].l)
            re(p[j].c);
    }
    re(c);
    return 0;
}
int main(){
    scanf("%d",&T);
    while(T--){
        int i,j,k,now=-1;
        init();
        for(i = 1;i<=L;i++){
            getchar();
            for(j = 1;j<=L;j++){
                tmp[i][j] = getchar();
            }
        }
        for(i = 1;i<=L;i++)
            for(j = 1;j<=L;j++){
                if(tmp[i][j] == '0')
                    for(k = 1;k<=L;k++)
                        addp(i,j,k);
                else
                    addp(i,j,tmp[i][j]-'0');
            }
        dfs();
        for(i = 1;i<=L;i++){
            for(j = 1;j<=L;j++)
                printf("%d",res[i][j]);
            putchar('\n');
        }
        putchar('\n');
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值