POJ3074 sudoku数独


#include "stdio.h"
#include "string.h"
#include<iostream>
using namespace std;
struct node
{
    int x,y;
    int s[10]; // 对于每个空格,数字i是否可用
    int sum; // 对于每个空格,一共可以填入的数字种数
}order[101];

int cnt; // 总空格数
char str[101];
int row[20][20],col[20][20],block[20][20]; //记录第i(行,列,小矩阵)的数字j是否已被占用
int table[101][101]; // 大矩阵
void init()
{
    int i,x,y;
    memset(row,0,sizeof(row));
    memset(col,0,sizeof(col));
    memset(block,0,sizeof(block));

    cnt=0;
    for (i=0;i<81;i++)
    {
        x=i/9;
        y=i%9;
        if (str[i]=='.')
        {
            table[x][y]=0;
            order[cnt].x=x;
            order[cnt].y=y;
            cnt++;
        }
        else
        {
            table[x][y]=str[i]-'0';
            row[x][str[i]-'0']=1;
            col[y][str[i]-'0']=1;
            block[x/3*3+y/3][str[i]-'0']=1;
        }
    }
}

void updata()
{
    int x,y,i,j,k;
    int oprow[10][10],opcol[10][10],opblock[10][10];  // 记录每行,列,小矩阵中数字k一共有几个可以放置的地方
    memset(oprow,0,sizeof(oprow));
    memset(opcol,0,sizeof(opcol));
    memset(opblock,0,sizeof(opblock));

    for (i=0;i<cnt;i++)
    {
        x=order[i].x;//i这个空位对应的横坐标 
        y=order[i].y;//i这个空位对应的纵坐标 
        if (table[x][y]==0)
        {
            order[i].sum=0;//
            memset(order[i].s,0,sizeof(order[i].s));//这个空位i没有数字可以放置 
            for (k=1;k<=9;k++)
                if (row[x][k]==0 && col[y][k]==0 && block[x/3*3+y/3][k]==0)//说明这个i空位放k合适 
                {
                    order[i].sum++;//i这个空位可用的数有多少个 
                    order[i].s[k]=1;//在这个空格i,记录这些合适的数字k 
                    oprow[x][k]++;//这一行可能很多个位置可以放k 
                    opcol[y][k]++;//这一列可能很多个位置可以放k 
                    opblock[x/3*3+y/3][k]++;//这个子矩阵可能很多位置可以放k//... 
                }
        }
    }
    //order[i].s[k],i这个空位能放k这个数字,从而确定是否只能放k这个数字。
    //如果只能,那么order[i].s[]其他都为0 
    for(i=0;i<9;i++)//对于某一行(某一列,某一子矩阵) 如果只有一个空位,且这个空位可以放置k,那么order[i].s[]其他都为0  
        for (k=1;k<=9;k++)//对于某个数字而言,某一行可以放它的位置只有一个 
        {
            if (oprow[i][k]==1) // 如果第i行,只有一个位置能放置数字k
            {
                for (j=0;j<cnt;j++)
                    if (order[j].x==i && table[order[j].x][order[j].y]==0 && order[j].s[k]==1)
                    {
                        order[j].sum=1;
                        memset(order[j].s,0,sizeof(order[j].s));
                        order[j].s[k]=1; //在这个空位j上就只能存放数字k 
                        break;
                    }
            }

            if (opcol[i][k]==1)
            {
                for (j=0;j<cnt;j++)
                    if (order[j].y==i && table[order[j].x][order[j].y]==0 && order[j].s[k]==1)
                    {
                        order[j].sum=1;
                        memset(order[j].s,0,sizeof(order[j].s));
                        order[j].s[k]=1;
                        break;
                    }
            }

            if (opblock[i][k]==1)
            {
                for (j=0;j<cnt;j++)
                    if (order[j].x/3*3+order[j].y/3==i && table[order[j].x][order[j].y]==0 && order[j].s[k]==1)
                    {
                        order[j].sum=1;
                        memset(order[j].s,0,sizeof(order[j].s));
                        order[j].s[k]=1;
                        break;
                    }
            }

        }
}

int getnow()
{
    int temp,mark,x,y;
    temp=10;
    mark=-1;
    for (int i=0;i<cnt;i++)
    {
        x=order[i].x;
        y=order[i].y;
        if (table[x][y]==0 && order[i].sum<temp)//找所有空位中可填数最少的那个空 
        {
            temp=order[i].sum;
            mark=i;
        }
    }
    return mark;
}
int  dfs(int w)
{
    int now,x,y,k;
    if (w==cnt) return 1;
    now=getnow();// 
    if (now==-1) return 0;

    x=order[now].x;
    y=order[now].y;
    for (k=1;k<=9;k++)
        if (order[now].s[k])//对于空格now,数字k是否可用,可用>0 
        {
            row[x][k]=1;
            col[y][k]=1;
            block[x/3*3+y/3][k]=1;
            table[x][y]=k;

            updata();
            if (dfs(w+1)==1) return 1;

            row[x][k]=0;
            col[y][k]=0;
            block[x/3*3+y/3][k]=0;
            table[x][y]=0;

            updata();
        }

    return 0;
}
void print()
{
        for (int i=0;i<9;i++)
        {
            for (int j=0;j<9;j++)
                printf("%d",table[i][j]);
//            cout<<endl;//...
        }
        printf("\n");
}
int main()
{
    int i,j;
    while (scanf("%s",str)!=EOF)
    {
        if (strcmp(str,"end")==0) break;
        init();
        updata();
        if(dfs(0))
            print();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值