weinan030416

导航

数独专题

输入

 

输入包含多组测试用例。

每个测试用例占一行,包含81个字符,代表数独的81个格内数据(顺序总体由上到下,同行由左到右)。

每个字符都是一个数字(1-9)或一个”.”(表示尚未填充)。

您可以假设输入中的每个谜题都只有一个解决方案。

文件结尾处为包含单词“end”的单行,表示输入结束。

 

输出

 

每个测试用例,输出一行数据,代表填充完全后的数独。

 

输入样例 1 

.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

输出样例 1

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936
#include<iostream>
#include<algorithm>
using namespace std;

const int N=9;
int ones[1<<N],LOG[1<<N];
int row[N],col[N],block[3][3];
string str;

inline int lowbit(int x)
{
    return x&-x;
}

void init()
{
    for(int i=0;i<N;i++)    row[i]=col[i]=(1<<N)-1;
    
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        block[i][j]=(1<<N)-1;
}

inline int get(int x,int y)
{
    return row[x]&col[y]&block[x/3][y/3];
}


bool dfs(int cnt)
{
    if(!cnt)    return true;
    int minv=10;
    int x,y;
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
        if(str[i*9+j]=='.')
        {
            int t=ones[get(i,j)];
            if(t<minv)
            {
                minv=t;
                x=i;
                y=j;
            }
        }
        for(int i=get(x,y);i;i-=lowbit(i))
        {
            int t=LOG[lowbit(i)];
            row[x]-=1<<t;
            col[y]-=1<<t;
            block[x/3][y/3]-=1<<t;
            str[x*9+y]='1'+t;
            if(dfs(cnt-1))    return true;
            row[x]+=1<<t;
            col[y]+=1<<t;
            block[x/3][y/3]+=1<<t;
            str[x*9+y]='.';
        }
        return false;
}
int main()
{
    for(int i=0;i<N;i++) LOG[1<<i]=i;
    for(int i=0;i<1<<N;i++)
    {
        int s=0;
        for(int j=i;j;j-=lowbit(j))    s++;
        ones[i]=s;
    }
    
    while(cin>>str,str[0]!='e')
    {
        init();
        int cnt=0;
        for(int i=0,k=0;i<N;i++)
            for(int j=0;j<N;j++,k++)
            if(str[k]!='.')
            {
                int t=str[k]-'1';
                row[i]-=1<<t;
                col[j]-=1<<t;
                block[i/3][j/3]-=1<<t;
            }
            else    cnt++;
            
            dfs(cnt);
            cout<<str<<endl;
    }
}

 自己写的,不考虑九宫格,有bug

#include<iostream>
using namespace std;
char Sudoku[10][10];

bool Notok(int x,int y,char t)
{
    
    for(int i=0;i<9;i++)//横方向 
    {
        if(Sudoku[x][i]==t)
        return true;
    }
    
    for(int i=0;i<9;i++)//竖方向 
    {
        if(Sudoku[i][y]==t)
        return true;
    }
    
    if(x==y)//斜方向 
    {
        for(int i=0;i<9;i++)
        {
            if(Sudoku[i][i]==t)
            return true;
        }
    }
    
    if(x==(8-y))//斜反方向 
    {
        for(int i=0;i<9;i++)
        {
            if(Sudoku[i][8-i]==t)
            return true;
        }
    } 
    
    return false;
}

void dfs(int x,int y)//正在填x,y 
{
    if(y==9)//填完了 
    {
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            { 
                cout<<Sudoku[i][j]<<" ";
            }    
            cout<<endl;
        }
        cout<<endl;
        return;
    } 
    
    if(Sudoku[x][y]!='.')//是数字,填下一个 
    {
        if(x==8)
        {
            dfs(0,y+1); 
        }
        
        else
        {
            dfs(x+1,y);
        }
        
    }
    
    else if(Sudoku[x][y]=='.')//是空格,需要填数字 
    {
        for(int i=1;i<=9;i++)//一个个尝试 
        {
            char t=i+'0';
            
            if(!Notok(x,y,t))//能填t
            {
                Sudoku[x][y]=t; 
                if(x==8)
                {
                    int tx=0,ty=y+1; 
                    dfs(tx,ty); 
                    Sudoku[tx][ty]='.'; 
                }
                
                else
                {
                    int tx=x+1,ty=y;
                    dfs(tx,ty);
                    Sudoku[tx][ty]='.';
                }
            }
                
        }
    } 
    
}

int main()
{
    int N;
    cin>>N;//数独个数 
    while(N--)
    {
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                cin>>Sudoku[i][j];
            }    
        }
        dfs(0,9);//输出原数独 
        cout<<endl; 
        dfs(0,0); //从0,0开始深搜 
    }
}

考虑九宫格,有bug

#include<iostream>
using namespace std;
char Sudoku[10][10];

bool Notoksquare(int x,int y,char t)
{
    for(int i=x-2;i<=x+2;i++)
    {
        for(int j=y-2;j<=y+2;j++)
        {
            if((x/3==j/3)&&(y/3==j/3)&&(Sudoku[i][j]==t))
            return true;
        }
    }
    return false;
}

bool Notok(int x,int y,char t)
{
    
    for(int i=0;i<9;i++)//横方向 
    {
        if(Sudoku[x][i]==t)
        return true;
    }
    
    for(int i=0;i<9;i++)//竖方向 
    {
        if(Sudoku[i][y]==t)
        return true;
    }
    
    if(x==y)//斜方向 
    {
        for(int i=0;i<9;i++)
        {
            if(Sudoku[i][i]==t)
            return true;
        }
    }
    
    if(x==(8-y))//斜反方向 
    {
        for(int i=0;i<9;i++)
        {
            if(Sudoku[i][8-i]==t)
            return true;
        }
    } 
    
    if(Notoksquare(x,y,t))
    return true;
    
    return false;
}

void dfs(int x,int y)//正在填x,y 
{
    if(y==9)//填完了 
    {
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            { 
                cout<<Sudoku[i][j]<<" ";
            }    
            cout<<endl;
        }
        cout<<endl;
        return;
    } 
    
    if(Sudoku[x][y]!='.')//是数字,填下一个 
    {
        if(x==8)
        {
            dfs(0,y+1); 
        }
        
        else
        {
            dfs(x+1,y);
        }
        
    }
    
    else if(Sudoku[x][y]=='.')//是空格,需要填数字 
    {
        for(int i=1;i<=9;i++)//一个个尝试 
        {
            char t=i+'0';
            
            if(!Notok(x,y,t))//能填t
            {
                Sudoku[x][y]=t; 
                if(x==8)
                {
                    int tx=0,ty=y+1; 
                    dfs(tx,ty); 
                    Sudoku[tx][ty]='.'; 
                }
                
                else
                {
                    int tx=x+1,ty=y;
                    dfs(tx,ty);
                    Sudoku[tx][ty]='.';
                }
            }
                
        }
    } 
    
}

int main()
{
    int N;
    cin>>N;//数独个数 
    while(N--)
    {
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                cin>>Sudoku[i][j];
            }    
        }
        dfs(0,9);//输出原数独 
        cout<<endl; 
        dfs(0,0); //从0,0开始深搜 
    }
}

 

 

posted on 2023-01-31 15:39  楠030416  阅读(20)  评论(0编辑  收藏  举报