数独

13年9月25号写的数独程序,虽然不怎么高大上,不过还是记录下。。

#include<iostream>
#include<cstdio>
#include<stack>
#include<set>
using namespace std;

//每行、列、小九宫中未用数字
set<char>set_row[9];
set<char>set_col[9];
set<char>set_area[9];

char grid[10][10];

//保存正在尝试的填充
struct stak
{
    char val;
    int row;
    int col;
    stak(int r,int c,int v):val(v),row(r),col(c){}
    stak(){}
};
stack<stak>stk;

//大于v的第一个未用数字,不大于v的为已经尝试但失败的数字,所以不再考虑
char get_val(int r,int c,int area,char v='*')
{
    set<char>::iterator it1,it2,it3;
    it1=set_row[r].begin();
    it2=set_col[c].begin();
    it3=set_area[area].begin();

    while(1)
    {
        if(it1==set_row[r].end()||it2==set_col[c].end()||it3==set_area[area].end())
        {
            return '*';
        }
        if(*it1==*it2&&*it2==*it3)
        {
            if(*it1<=v)
            {
                it1++;
                it2++;
                it3++;
                continue;
            }
            else break;
        }
        if(*it1<=*it2&&*it1<=*it3){it1++;continue;};
        if(*it2<=*it1&&*it2<=*it3){it2++;continue;};
        if(*it3<=*it1&&*it3<=*it2){it3++;continue;};
    }
    return *it1;
}

int main()
{
    //while(1)
    {
		//清空栈
        while(!stk.empty())
        {
            stk.pop();
        }

        for(int i=0;i<9;i++)
        {
		
			//初始化每行、列、小九宫的未用数字为1-9
            set_row[i].clear();
            set_col[i].clear();
            set_area[i].clear();
            for(int j=1;j<=9;j++)
            {
                set_row[i].insert(j+'0');
                set_col[i].insert(j+'0');
                set_area[i].insert(j+'0');
            }
        }

		//读入数独
        for(int i=0;i<9;i++)
        {
            scanf("%s",grid[i]);
        }
		
		//把每行、列、 小九宫中已有的数字从未用集合中去除
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                if(grid[i][j]=='*')continue;

                int area_grid=i/3*3+j/3;
                set_area[area_grid].erase(grid[i][j]);
                set_row[i].erase(grid[i][j]);
                set_col[j].erase(grid[i][j]);
            }
        }
		
		//*表示该处为未填数字的格
        char next='*';
		
        while(1)
        {
			//找到最近的未填数字处
            int r=-1,c=-1;
            for(int i=0;i<9;i++)
            {
                for(int j=0;j<9;j++)
                {
                    if(grid[i][j]=='*')
                    {
                        r=i;c=j;break;
                    }
                }
                if(r!=-1&&c!=-1)break;
            }
            if(r==-1&&c==-1)break;

			//在第几个小九宫中
            int ar=r/3*3+c/3;

			//next表示该位置已尝试过的最小值
            char tmp=get_val(r,c,ar,next);

            if(tmp!='*')
            {
                set_row[r].erase(tmp);
                set_col[c].erase(tmp);
                set_area[ar].erase(tmp);
                stk.push(stak(r,c,tmp));
                //printf("tmp %d %d %c \n",r,c,tmp);
                grid[r][c]=tmp;
                next='*';
            }
            else
            {
                if(stk.empty())
                {
                    printf("input maybe error!or bug??\n");
                }
                stak s=stk.top();
                stk.pop();
                set_row[s.row].insert(s.val);
                set_col[s.col].insert(s.val);
                set_area[s.row/3*3+s.col/3].insert(s.val);
                grid[s.row][s.col]='*';
				
                next=s.val;
            }
        }
		
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                printf("%c ",grid[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值