zoukankan      html  css  js  c++  java
  • 数独求解问题(DFS+位运算优化)

    In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

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

    Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

    Input

    The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

    Output

    For each test case, print a line representing the completed Sudoku puzzle.

    Sample Input

    .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
    ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
    end

    Sample Output

    527389416819426735436751829375692184194538267268174593643217958951843672782965341
    416837529982465371735129468571298643293746185864351297647913852359682714128574936

    思路:DFS解这道题有点极限,需要优化的东西比较复杂,参考了网上的位运算优化,终于以700ms的解决了,如果不位运算优化很难去不超时的去解这道问题

    附上原超时代码,此代码修改一下应该可以过F题,单纯的求数独的题

    代码:

    ​
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<set>
    #include<stack>
    #include<map> 
    #define MAX 10005
    
    typedef long long ll;
    
    using namespace std;
     
    int cnt,flag;
    int Map[10][10],vistrow[10][10],vistcol[10][10],vistkaui[10][10][10];
    struct node
    {
    	int x,y;
    }a[100];
     
    void DFS(int x)
    {
    	if(x == cnt)
    	{
    		flag = 1;
    		return;
    	}
    	int I = a[x].x;
    	int J = a[x].y;
    	for(int i = 1; i < 10; i++)
    	{
    		if(!vistrow[I][i] && !vistcol[J][i] && !vistkaui[I/3][J/3][i])
    		{
    			Map[I][J] = i;
    			vistrow[I][i] = 1;
    			vistcol[J][i] = 1;
    			vistkaui[I/3][J/3][i] = 1;
    			DFS(x+1);
    			if(!flag)
    			{
    				Map[I][J] = '.';
    				vistrow[I][i] = 0;
    				vistcol[J][i] = 0;
    				vistkaui[I/3][J/3][i] = 0;
    			}
    		}
    	}
    }
     
    int main()
    {
    	int T;
    	
    	while(1)
    	{
    		memset(vistrow,0,sizeof(vistrow));
    		memset(vistcol,0,sizeof(vistcol));
    		memset(vistkaui,0,sizeof(vistkaui));
     
    		cnt = 0;
    		flag = 0;
    		
    		for(int i = 0; i < 9; i++)
    		{
    			
    			
    			for(int j = 0; j < 9; j++)
    			{
    			    scanf("%c",Map[i][j]);
     
    				if(Map[i][j] == '.')
    				{
    					a[cnt].x = i;
    					a[cnt++].y = j;
    				}
    				else
    				{
    					vistrow[i][Map[i][j]-'] = 1;
    					vistcol[j][Map[i][j]] = 1;
    					vistkaui[i/3][j/3][Map[i][j]] = 1;
    				}
    			}
    		}
    		DFS(0);
    		for(int i = 0; i < 9; i++)
    			for(int j = 0; j < 9; j++)
    			{
    				if(j == 8)
    					printf("%c
    ",Map[i][j]);
    				else
    					printf("%c",Map[i][j]);
    			}
    	}
    	return 0;
    }
    
    ​

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<set>
    #include<stack>
    #include<map> 
    #define MAX 10005
    
    using namespace std;
    char Map[10][10];
    int vistrow[10],vistcol[10];
    int grid[10],rec[512],num[512];
    
    inline int g(int x,int y) 
    {
        return (x/3)*3+y/3;
    }
    inline void flip(int x,int y,int to) 
    {
        vistrow[x]^=1<<to;
        vistcol[y]^=1<<to;
        grid[g(x,y)]^=1<<to;
    }
    bool DFS(int x) 
    {
        if(x==0) return 1;
        int minn=10,xx,yy;
        for(int i=0;i<9;i++) {
            for(int j=0;j<9;j++) 
    		{
                if(Map[i][j]=='.') 
    			{
                    int val=vistrow[i]&vistcol[j]&grid[g(i,j)];
                    if(!val) return 0;
                    if(rec[val]<minn) {
                        minn=rec[val],xx=i,yy=j;
                    }
                }
            }
        }
        int val=vistrow[xx]&vistcol[yy]&grid[g(xx,yy)];
        for(;val;val-=val&-val) {
            int to=num[val&-val];
            Map[xx][yy]=to+'1';
            flip(xx,yy,to);
            if(DFS(x-1)) return 1;
            flip(xx,yy,to);
            Map[xx][yy]='.';
        }
        return 0;
    }
    int main() {
        for(int i=0;i<1<<9;i++) {
            for(int j=i;j;j-=j&-j)
                rec[i]++;
        }
        for(int i=0;i<9;i++) {
            num[1<<i]=i;
        }
        char s[100];
        while(~scanf("%s",s)&&s[0]!='e') {
            for(int i=0;i<9;i++) 
    		vistrow[i]=vistcol[i]=grid[i]=(1<<9)-1;
            int tot=0;
            for(int i=0;i<9;i++) {
                for(int j=0;j<9;j++) {
                    Map[i][j]=s[i*9+j];
                    if(Map[i][j]!='.') flip(i,j,Map[i][j]-'1');
                    else ++tot;
                }
            }
            DFS(tot);
            for(int i=0;i<9;i++)
                for(int j=0;j<9;j++)
                    printf("%c",Map[i][j]);
    
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    20145215《Java程序设计》第4周学习总结
    20145215《Java程序设计》第3周学习总结
    20145215《Java程序设计》第2周学习总结
    关于开源中国的代码托管
    问卷调查
    2019年12月29日 回怼老王
    cnblogs今天挂了
    感悟别人的感悟——写在2020年前一天
    心情随笔_20191231
    js事件冒泡和捕捉
  • 原文地址:https://www.cnblogs.com/Staceyacm/p/10781797.html
Copyright © 2011-2022 走看看