• POJ


    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

    最后终于碰上了位运算优化的题目,虽然学会了发现不难,我们就来看看这个题怎么做!

    首先明确一件事,&代表两个状态取交集,这样就更快的到两个状态的共有部分,详解在代码中!

    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<set>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<stack>
    #include<bitset>
    #include<cstdio>
    #include<cstring>
    #define Swap(a,b) a^=b^=a^=b
    #define cini(n) scanf("%d",&n)
    #define cinl(n) scanf("%lld",&n)
    #define cinc(n) scanf("%c",&n)
    #define cins(s) scanf("%s",s)
    #define coui(n) printf("%d",n)
    #define couc(n) printf("%c",n)
    #define coul(n) printf("%lld",n)
    #define speed ios_base::sync_with_stdio(0)
    #define Max(a,b) a>b?a:b
    #define Min(a,b) a<b?a:b
    #define mem(n) memset(n,0,sizeof(n))
    using namespace std;
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    const int maxn=1e6+10;
    const double esp=1e-9;
    //-------------------------------------------------------//
    
    const int N=9;
    char a[N*N+N];
    int R[9],L[9],C[3][3];
    int one[1<<N],mp[1<<N];//通过lowbit,找到每一位1对应的位置
    inline int lowbit(int n)
    {
        return n&-n;
    }
    inline void init()//初始化,每个状态位赋值为1
    {
    
        for(int i=0; i<N; i++){
            R[i]=L[i]=(1<<N)-1;
        }
    
        for(int i=0; i<3; i++)
            for(int j=0; j<3; j++)
                C[i][j]=(1<<N)-1;
    }
    inline int get(int x,int y) // 找到当前位置能填的状态
    {
        return L[y]&R[x]&C[x/3][y/3];
    }
    bool dfs(int n)
    {
        if(n==0)
            return 1;
       //cout<<n<<' ';
        int x,y,mini=10;
        for(int i=0; i<N; i++) //寻找最少填数点
        {
            for(int j=0; j<N; j++)
            {
                if(a[i*N+j]!='.')
                    continue;
                int minT=one[get(i,j)];
                if(minT<mini)
                {
                    x=i;
                    y=j;
                    mini=minT;
                }
            }
        }
        //cout<<x<<' '<<y<<endl;
        int T=get(x,y);
       //cout<<T<<endl;
        for(int i=T; i; i-=lowbit(i)) //遍历每一位1所代表的的状态,看不懂状态,打个表就行了。
        {
            int w=mp[lowbit(i)];
            a[x*N+y]=w+'1';
            R[x]-=1<<w;
            L[y]-=1<<w;
            C[x/3][y/3]-=1<<w;
            if(dfs(n-1))
                return 1;
            a[x*N+y]='.';
            R[x]+=1<<(w);
            L[y]+=1<<(w);
            C[x/3][y/3]+=1<<w;
        }
        return 0;
    }
    int main()
    {
        for(int i=0; i< 1<<N; i++)
        {
            int s=0;
            for(int j=i; j; j-=lowbit(j))s++;
            one[i]=s; //统计2的N次方内所有的数的1的个数,这样用到时就不用算了
        }
        for(int i=0;i<N;i++) mp[1<<i]=i;
        while(cin>>a&&a[0]!='e')
        {
            int k=0,cnt=0;
            init();
            for(int i=0; i<N; i++) //预处理,得到还有多少数需要填,处理一下状态
            {
                for(int j=0; j<N; j++,k++)
                {
                    if(a[i*N+j]=='.')
                    {
                        cnt++;
                        continue;
                    };
                    int T=(1<<(a[k]-'1'));
                    R[i]-=T;//代表这一行的状态中填了a[k]这个数了
                    L[j]-=T;
                    C[i/3][j/3]-=T;
                }
            }
            if(dfs(cnt))
                cout<<a<<endl;
        }
    }
  • 相关阅读:
    GetWindowThreadProcessId
    为什么要学制作外挂
    博客系统架构对比分析
    C# 数据库访问通用类 (ADO.NET)
    转:配置 SQL Server 2005 远程调试存储过程
    腾讯QQ空间g_tk算法
    BurstNET的linux vps 安装Kloxo面板后一切正常 今天重启导致错误Could not connect to Mysql server
    service的生命周期回调方法
    服务的生命周期回调方法
    点阵字库在JAVA中的实现
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/11338754.html
Copyright © 2020-2023  润新知