POJ 2676 数码问题DLX

Sudoku

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 13023   Accepted: 6455   Special Judge

Description

Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the cells are written decimal digits from 1 to 9. The other cells are empty. The goal
is to fill the empty cells with decimal digits from 1 to 9, one digit per cell, in such way that in each row, in each column and in each marked 3x3 subsquare, all the digits from 1 to 9 to appear. Write a program to solve a given Sudoku-task.

Input

The input data will start with the number of the test cases. For each test case, 9 lines follow, corresponding to the rows of the table. On each line a string of exactly 9 decimal digits is given, corresponding to the cells in
this line. If a cell is empty it is represented by 0.

Output

For each test case your program should print the solution in the same format as the input data. The empty cells have to be filled according to the rules. If solutions is not unique, then the program may print any one of them.

Sample Input

1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107

Sample Output

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127

与POJ 3076一样的方法。

代码:

/* ***********************************************
Author :_rabbit
Created Time :2014/5/1 8:56:15
File Name :F.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
struct DLX{
    const static int maxn=20010;
    #define FF(i,A,s) for(int i = A[s];i != s;i = A[i])
    int L[maxn],R[maxn],U[maxn],D[maxn];
    int size,col[maxn],row[maxn],s[maxn],H[maxn];
    bool vis[70];
	int ans[maxn],cnt;
    void init(int m){
        for(int i=0;i<=m;i++){
            L[i]=i-1;R[i]=i+1;U[i]=D[i]=i;s[i]=0;
        }
        memset(H,-1,sizeof(H));
        L[0]=m;R[m]=0;size=m+1;
    }
	void link(int r,int c){
         U[size]=c;D[size]=D[c];U[D[c]]=size;D[c]=size;
         if(H[r]<0)H[r]=L[size]=R[size]=size;
         else {
             L[size]=H[r];R[size]=R[H[r]];
             L[R[H[r]]]=size;R[H[r]]=size;
         }
         s[c]++;col[size]=c;row[size]=r;size++;
     }
	void del(int c){//精确覆盖
        L[R[c]]=L[c];R[L[c]]=R[c];
        FF(i,D,c)FF(j,R,i)U[D[j]]=U[j],D[U[j]]=D[j],--s[col[j]];
    }
    void add(int c){  //精确覆盖
        R[L[c]]=L[R[c]]=c;
        FF(i,U,c)FF(j,L,i)++s[col[U[D[j]]=D[U[j]]=j]];
    }
	bool dfs(int k){//精确覆盖
        if(!R[0]){
            cnt=k;return 1;
        }
        int c=R[0];FF(i,R,0)if(s[c]>s[i])c=i;
        del(c);
        FF(i,D,c){
            FF(j,R,i)del(col[j]);
            ans[k]=row[i];if(dfs(k+1))return true;
            FF(j,L,i)add(col[j]);
        }
        add(c);
        return 0;
    }
    void remove(int c){//重复覆盖
        FF(i,D,c)L[R[i]]=L[i],R[L[i]]=R[i];
    }
     void resume(int c){//重复覆盖
         FF(i,U,c)L[R[i]]=R[L[i]]=i;
     }
    int A(){//估价函数
        int res=0;
        memset(vis,0,sizeof(vis));
        FF(i,R,0)if(!vis[i]){
                res++;vis[i]=1;
                FF(j,D,i)FF(k,R,j)vis[col[k]]=1;
            }
        return res;
    }
    void dfs(int now,int &ans){//重复覆盖
        if(R[0]==0)ans=min(ans,now);
        else if(now+A()<ans){
            int temp=INF,c;
            FF(i,R,0)if(temp>s[i])temp=s[i],c=i;
            FF(i,D,c){
                remove(i);FF(j,R,i)remove(j);
                dfs(now+1,ans);
                FF(j,L,i)resume(j);resume(i);
            }
        }
    }
}dlx;
const int SLOT=0;
const int ROW=1;
const int COL=2;
const int SUB=3;
int encode(int a,int b,int c){
	return a*81+b*9+c+1;
}
void decode(int code,int &a,int &b,int &c){
	code--;
	c=code%9;code/=9;
	b=code%9;code/=9;
	a=code;
}
char str[20][20];
int main()
{
     //freopen("data.in","r",stdin);
     //freopen("data.out","w",stdout);
     int T;
	 cin>>T;
	 while(T--){
		 for(int i=0;i<9;i++)scanf("%s",str[i]);
		 dlx.init(324);
		 for(int r=0;r<9;r++)
			 for(int c=0;c<9;c++)
				 for(int k=1;k<=9;k++)
					 if(str[r][c]==‘0‘||str[r][c]==k+‘0‘){
						 int p=encode(r,c,k-1);
						 dlx.link(p,encode(SLOT,r,c));
						 dlx.link(p,encode(ROW,r,k-1));
						 dlx.link(p,encode(COL,c,k-1));
						 dlx.link(p,encode(SUB,(r/3)*3+c/3,k-1));
					 }
		 dlx.dfs(0);
		// cout<<"jjjdfjfj"<<endl;
		//cout<<"hhahha: "<<dlx.cnt<<endl;
		 for(int i=0;i<dlx.cnt;i++){
			 int r,c,v;
			 decode(dlx.ans[i],r,c,v);
			// cout<<"pppp"<<endl;
			// cout<<"han "<<r<<" "<<c<<" "<<v<<endl;
			 str[r][c]=v+‘1‘;
		 }
		 for(int i=0;i<9;i++)printf("%s\n",str[i]);
	 }
     return 0;
}

POJ 2676 数码问题DLX,布布扣,bubuko.com

时间: 2024-08-03 13:28:33

POJ 2676 数码问题DLX的相关文章

poj 2676 数独 Dancing-Links(DLX)

题目大意:....数独还用我说么 首先一般的解法都是爆搜,爆搜的话绝对懒得做..于是我作死去学了Dancing-Links数据结构优化的X算法,简称DLX算法 Dancing-Links虽然名字好听,但是其实实质就是双向十字链表..但是由于调试的时候各种挂,指针还看着及其闹心(经常调试链式结构的人一定深有同感),所以只能在调试区各种加指针删指针,来回飞舞的指针,即Dancing-Links... 这算法的作者太有才了,不得不说.... DLX算法主要解决的是精确覆盖问题,具体做法见 http:/

POJ 2676 Sudoku (搜索,Dancing Links)

题目: http://poj.org/problem?id=2676 题意: 数独,每行1-9,每列1-9,每3*3小格1-9,填数,不能重复 方法:Dancing Links(16ms)或者DFS暴搜(400-900ms) Dancing Links(DLX) 是为了解决矩阵精确覆盖问题的算法,算法效率非常高 使用DLX解决的问题必须转化为矩阵精确覆盖问题: 1.DLX详解: http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html 2

(搜索) poj 2676

M - Sudoku Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2676 Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on

poj 2676 如何填满九宫格

Sudoku Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main Special Judge [Submit] [Status] [Discuss] Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to

poj 2676 Sudoku (dfs)

链接:poj 2676 题意:给定一个未完成的数独,0是待填位置,其他均为已填入的数字.如果能将其 补充完整,则输出补充完整的数独(有多组答案输出任意一组),否则原样输出 数独:一个9行9列的网格,包括9个3*3的子网格,要求每行.每列.每个子网格内 都只能使用一次1-9中的一个数字, 即每行.每列.每个子网格内都不允许出现相同的数字. 分析:对于每一个未填的格,依次判断它所在行.列.子网格是否填了1-9, 若都未填,先填上该值,继续搜索, 若无法填写了,再回溯,填上其他可能的值,继续搜索 看别

ACM : POJ 2676 SudoKu DFS - 数独

SudoKu Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu POJ 2676 Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the c

POJ 2676 Sudoku (数独)

经典搜索问题,主要是时间上的优化,我用了三个辅助数组记录信息 row[i][k] = 1表示第i行数字k已经被使用,col[j][k] = 1表第j列数字k已经被使用,blo[i][k]表示第i个小九宫格中数字k已经被使用 还有很重要的一个优化(没有优化的话可能会超时,或者非常慢,像POJ讨论区里有很多说正着搜超时,倒着搜0ms,这的确是一个可以用的方法,但是有一定的随机性),每次填数字时,先扫描一遍整个矩阵,找出可选数字情况最少的那个0所在的地方,优先填这里,这样会使得搜索树尽可能的"瘦&qu

POJ 2676/2918 数独(dfs)

思路:记录每行每列每一个宫已经出现的数字就可以.数据比較弱 另外POJ 3074 3076 必须用剪枝策略.但实现较麻烦,还是以后学了DLX再来做吧 //Accepted 160K 0MS #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N =15; char sudo[N][N]; bool vi

POJ 2676 Sudoku

题目链接:http://poj.org/problem?id=2676 数独问题.用dancing links解决. 建图参考 http://wenku.baidu.com/link?url=3Tk5gVYew3mSQ2f2LxDODxPg3v-yqJPUaEkuZpfkHTxfSPQuM_n8TGl2Swp68XQY9MYN2BENZ-pmv9dpoh3Ulqt1lT-ZNo90jcJyi1eXasm 要注意的就是搜索的时候 要先搜索 那一列中节点最少的,否则时间会很长. 1 #include