暴力搜索

#include<stdio.h>
#include<iostream>
#include<fstream>
using namespace std;
int a[10][10];
int Max=0;
int sudoku(int x,int y,bool *occupy)/* occupy为传递给函数的数组头指针*/
{
        int rx=x%3;
        int ry=y%3;
        int bx,by;
        if (rx==0) bx=x-2;
        else if (rx==1) bx=x;
        else if (rx==2)    bx=x-1;
        if (ry==0) by=y-2;
        else if (ry==1) by=y;
        else if (ry==2) by=y-1;
        for (int i=bx;i<=bx+2;i++)
            for (int j=by;j<=by+2;j++)
                if (a[i][j]!=0)    occupy[a[i][j]]=false;
        return 0;
}
int count()
{
    int c=0;
    for(int i=1;i<10;i++)
        for (int j=1;j<10;j++)
            c+=a[i][j]*6;
    for(int i=2;i<9;i++)
        for (int j=2;j<9;j++)
            c+=a[i][j];
    for(int i=3;i<8;i++)
        for (int j=3;j<8;j++)
            c+=a[i][j];
    for(int i=4;i<7;i++)
        for (int j=4;j<7;j++)
            c+=a[i][j];
    c+=a[5][5];
    return c;
}
int dfs(int x,int y)
{
    int xx,yy;
    if (x>9)
    {
        int c=count();
        if (c>Max) Max=c;
        return 0;
    }
    if (a[x][y]!=0)
    {
        if (y<9) 
        {
            xx=x;
            yy=y+1;
        }
        else
        {
             xx=x+1;
             yy=1;
        }
        dfs(xx,yy);
    }
    else
    {
        bool occupy[10];/*occupy[i]表示i是否可以填入*/
        for (int i=1;i<10;i++)
            occupy[i]=true;
        for (int i=1;i<10;i++)/*坐标(x,y)所在列不能重复*/
            if (a[i][y]!=0) occupy[a[i][y]]=false;
        for (int j=1;j<10;j++)/*坐标(x,y)所在行不能重复*/
            if (a[x][j]!=0) occupy[a[x][j]]=false;
        sudoku(x,y,occupy);/*坐标(x,y)所在小九宫格不能重复*/
        for (int i=9;i>0;i--)
        {
            if (occupy[i])
            {
                a[x][y]=i;
                if (y<9)
                {
                    xx=x;
                    yy=y+1;
                }
                else 
                {
                    xx=x+1;
                    yy=1;
                }
                dfs(xx,yy);
                a[x][y]=0;
            }
        }
    }
    return 0;
}
int main()
{
    ifstream infile;
    infile.open("in.txt");
    ofstream outfile;
    outfile.open("out.txt");
    for (int i=1;i<=9;i++)
        for (int j=1;j<=9;j++)
        {
            int k;
            infile >> k;
            a[i][j]=k;
        }
    dfs(1,1);
    if (Max==0) outfile << -1 <<endl;
    else outfile << Max << endl;
    infile.close();
    outfile.close();
    return 0;
}

优化1:位运算

#include<stdio.h>
#include<iostream>
#include<fstream>
using namespace std;
#define getid(i,j) ((i-1)/3*3+(j-1)/3+1)
int a[10][10];
int r[10];
int c[10];
int sudoku[10];
int Max=0;
int count()
{
    int c=0;
    for(int i=1;i<10;i++)
        for (int j=1;j<10;j++)
            c+=a[i][j]*6;
    for(int i=2;i<9;i++)
        for (int j=2;j<9;j++)
            c+=a[i][j];
    for(int i=3;i<8;i++)
        for (int j=3;j<8;j++)
            c+=a[i][j];
    for(int i=4;i<7;i++)
        for (int j=4;j<7;j++)
            c+=a[i][j];
    c+=a[5][5];
    return c;
}
int dfs(int x,int y)
{
    int xx,yy;
    if (x>9)
    {
        int c=count();
        if (c>Max) Max=c;
        return 0;
    }
    if (a[x][y]!=0)
    {
        if (y<9) 
        {
            xx=x;
            yy=y+1;
        }
        else
        {
             xx=x+1;
             yy=1;
        }
        dfs(xx,yy);
    }
    else
    {
        int k=r[x]|c[y]|sudoku[getid(x,y)];
        for (int i=9;i>0;i--)
        {
            if (!((1<<(i-1))&k))
            {
                a[x][y]=i;
                r[x]|=1<<(i-1);
                c[y]|=1<<(i-1);
                sudoku[getid(x,y)]|=1<<(i-1);
                if (y<9)
                {
                    xx=x;
                    yy=y+1;
                }
                else 
                {
                    xx=x+1;
                    yy=1;
                }
                dfs(xx,yy);
                a[x][y]=0;
                r[x]^=1<<(i-1);
                c[y]^=1<<(i-1);
                sudoku[getid(x,y)]^=1<<(i-1);
            }
        }
    }
    return 0;
}
int main()
{
    ifstream infile;
    infile.open("in.txt");
    ofstream outfile;
    outfile.open("out.txt");
    for (int i=1;i<=9;i++)
        for (int j=1;j<=9;j++)
        {
            infile >> a[i][j];
            if (a[i][j]!=0)
            {
                r[i]|=1<<(a[i][j]-1);
                c[j]|=1<<(a[i][j]-1);
                sudoku[getid(i,j)]|=1<<(a[i][j]-1);
            }
        }
    dfs(1,1);
    if (Max==0) outfile << -1 <<endl;
    else outfile << Max << endl;
    infile.close();
    outfile.close();
    return 0;
}

优化2:按照空白的格内可填的数字个数由小到大搜索

#include<stdio.h>
#include<iostream>
#include<fstream>
using namespace std;
#define getid(i,j) ((i-1)/3*3+(j-1)/3+1)
int a[10][10];
int r[10];
int c[10];
int sudoku[10];
int Max=0;
int count()
{
    int c=0;
    for(int i=1;i<10;i++)
        for (int j=1;j<10;j++)
            c+=a[i][j]*6;
    for(int i=2;i<9;i++)
        for (int j=2;j<9;j++)
            c+=a[i][j];
    for(int i=3;i<8;i++)
        for (int j=3;j<8;j++)
            c+=a[i][j];
    for(int i=4;i<7;i++)
        for (int j=4;j<7;j++)
            c+=a[i][j];
    c+=a[5][5];
    return c;
}
int dfs(int x,int y)
{
    int xx,yy;
    if (x>9)
    {
        int c=count();
        if (c>Max) Max=c;
        return 0;
    }
    if (a[x][y]!=0)
    {
        if (y<9) 
        {
            xx=x;
            yy=y+1;
        }
        else
        {
             xx=x+1;
             yy=1;
        }
        dfs(xx,yy);
    }
    else
    {
        int k=r[x]|c[y]|sudoku[getid(x,y)];
        for (int i=9;i>0;i--)
        {
            if (!((1<<(i-1))&k))
            {
                a[x][y]=i;
                r[x]|=1<<(i-1);
                c[y]|=1<<(i-1);
                sudoku[getid(x,y)]|=1<<(i-1);
                if (y<9)
                {
                    xx=x;
                    yy=y+1;
                }
                else 
                {
                    xx=x+1;
                    yy=1;
                }
                dfs(xx,yy);
                a[x][y]=0;
                r[x]^=1<<(i-1);
                c[y]^=1<<(i-1);
                sudoku[getid(x,y)]^=1<<(i-1);
            }
        }
    }
    return 0;
}
int main()
{
    ifstream infile;
    infile.open("in.txt");
    ofstream outfile;
    outfile.open("out.txt");
    for (int i=1;i<=9;i++)
        for (int j=1;j<=9;j++)
        {
            infile >> a[i][j];
            if (a[i][j]!=0)
            {
                r[i]|=1<<(a[i][j]-1);
                c[j]|=1<<(a[i][j]-1);
                sudoku[getid(i,j)]|=1<<(a[i][j]-1);
            }
        }
    dfs(1,1);
    if (Max==0) outfile << -1 <<endl;
    else outfile << Max << endl;
    infile.close();
    outfile.close();
    return 0;
}

 

posted on 2014-04-13 11:06  武晓伟  阅读(196)  评论(0编辑  收藏  举报