CSU 1969 TFSudoku 特殊数独

题目:

Description

At some point or another, most computer science students have written a standard Sudoku solving program. A slight twist has been added to standard Sudoku to make it a bit more challenging.

Digits from 1 to 9 are entered in a 6x6 grid so that no number is repeated in any row, column or 3x2 outlined region as shown below. Some squares in the grid are split by a slash and need 2 digits entered in them. The smaller number always goes above the slash.

For this problem, you will write a program that takes as input an incomplete puzzle grid and outputs the puzzle solution grid.

Input

The first line of input contains a single decimal integer P, (1 ≤ P ≤ 100), which is the number of data sets that follow. Each data set should be processed identically and independently.

Each data set consists of 7 lines of input. The first line of the data set contains the data set number, K. The remaining 6 lines represent an incomplete Tight-Fit Sudoku grid, each line has 6 data elements, separated by spaces. A data element can be a digit (1-9), a dash ('-') for a blank square or two of these separated by a slash ('/')

Output

For each data set there are 7 lines of output. The first output line consists of the data set number, K. The following 6 lines of output show the solution grid for the corresponding input data set. Each line will have 6 data elements, separated by spaces. A data element can be a digit (1-9), or 2 digits separated by a slash (‘/’).

Sample Input

1
1
-/- -/5 4 3 2 -/-
- 6 -/- -/- - -/-
- 7/- - -/- -/- 2
8 -/- -/- - -/3 -
-/- - -/- -/- 4 -
-/- 8 7 6 5/- -/-

Sample Output

1
7/9 1/5 4 3 2 6/8 
3 6 2/8 1/9 7 4/5 
1 7/9 3 4/5 6/8 2 
8 2/4 5/6 7 1/3 9 
5/6 3 1/9 2/8 4 7 
2/4 8 7 6 5/9 1/3 

一个加了特殊规则的数独,6x6的格子中会有斜杠出现,出现斜杠的格子斜杠上下一起要填2个数字,且上面的必须比下面小。

直接枚举不知道能不能过,我采用模拟人做数独的方法,先使用排除法,把能确定的数字都填上,没有可以确定的数字之后再选择可能性比较少的格子进行假设。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <math.h>
#include <algorithm>
#include <map>
#include <string>

#define INF 0x3f3f3f3f
#define MS(x,y) memset(x, y, sizeof(x))
#define MOD 1000000007
#define LL long long int

using namespace std;

struct node
{
    int x,y;
}z[10][10];

int f[10][10][2][10];//前2维表示第几行第几列。第3维表示格子的上下。第4维表示那些数字不能填,0记录剩余可填的数字数
bool xie[10][10];//记录有斜杠的格子
int T;

char s[5];

void show()
{
    //printf("*****************************\n");
    for(int i=0;i<6;++i)
    {
        for(int j=0;j<6;++j)
        {
            if(xie[i][j])
            {
                printf("%d/%d ", z[i][j].x, z[i][j].y);
            }
            else
                printf("%d ", z[i][j].x);
        }
        printf("\n");
    }
    //printf("*****************************\n");
}

void tian(int a, int b, int x, int y)//填数字,并且把周围的格子出现这个数字的可能性去掉,x表示斜杠上的数字,y表示斜杠下的数字
{
    int xoff = b/3*3;
    int yoff = a/2*2;
    if(x != 0)
    {
        z[a][b].x = x;
        for(int i=0;i<6;++i)
        {
            if(f[a][i][0][x] == 0)
                --f[a][i][0][0];
            f[a][i][0][x] = 1;
            if(f[i][b][0][x] == 0)
                --f[i][b][0][0];
            f[i][b][0][x] = 1;
            if(f[a][i][1][x] == 0)
                --f[a][i][1][0];
            f[a][i][1][x] = 1;
            if(f[i][b][1][x] == 0)
                --f[i][b][1][0];
            f[i][b][1][x] = 1;
        }
        for(int i=0;i<2;++i)
        {
            for(int j=0;j<3;++j)
            {
                if(f[yoff+i][xoff+j][0][x] == 0)
                    --f[yoff+i][xoff+j][0][0];
                f[yoff+i][xoff+j][0][x] = 1;
                if(f[yoff+i][xoff+j][1][x] == 0)
                    --f[yoff+i][xoff+j][1][0];
                f[yoff+i][xoff+j][1][x] = 1;
            }
        }
        if(xie[a][b])
        {
            for(int i=x-1;i>0;--i)
            {
                if(f[a][b][1][i] == 0)
                    --f[a][b][1][0];
                f[a][b][1][i] = 1;
            }
        }
    }
    if(y != 0 && x != y)
    {
        z[a][b].y = y;
        for(int i=0;i<6;++i)
        {
            if(f[a][i][0][y] == 0)
                --f[a][i][0][0];
            f[a][i][0][y] = 1;
            if(f[i][b][0][y] == 0)
                --f[i][b][0][0];
            f[i][b][0][y] = 1;
            if(f[a][i][1][y] == 0)
                --f[a][i][1][0];
            f[a][i][1][y] = 1;
            if(f[i][b][1][y] == 0)
                --f[i][b][1][0];
            f[i][b][1][y] = 1;
        }
        for(int i=0;i<2;++i)
        {
            for(int j=0;j<3;++j)
            {
                if(f[yoff+i][xoff+j][0][y] == 0)
                    --f[yoff+i][xoff+j][0][0];
                f[yoff+i][xoff+j][0][y] = 1;
                if(f[yoff+i][xoff+j][1][y] == 0)
                    --f[yoff+i][xoff+j][1][0];
                f[yoff+i][xoff+j][1][y] = 1;
            }
        }
        if(xie[a][b])
        {
            for(int i=y+1;i<10;++i)
            {
                if(f[a][b][0][i] == 0)
                    --f[a][b][0][0];
                f[a][b][0][i] = 1;
            }
        }
    }
}

bool judge()//判断是否得出答案
{
    for(int i=0;i<6;++i)
    {
        for(int j=0;j<6;++j)
        {
            if(xie[i][j])
            {
                if(z[i][j].x == 0 || z[i][j].y == 0)
                    return false;
            }
            else
            {
                if(z[i][j].x == 0)
                    return false;
            }
        }
    }
    return true;
}

bool solve()
{
    while(1)
    {
        int x=0,y=0,MIN = 9,ff = 0;
        bool istian = false;
        bool maodun = false;
        for(int i=0;i<6;++i)
        {
            for(int j=0;j<6;++j)
            {
                if(xie[i][j])
                {
                    if(z[i][j].x == 0)
                    {
                        if(f[i][j][0][0] == 0)
                        {
                            maodun = true;
                            //printf("*****(%d,%d)矛盾\n", i, j);
                            break;
                        }
                        else if(f[i][j][0][0] == 1)
                        {
                            for(int ii=1;ii<10;++ii)
                            {
                                if(f[i][j][0][ii] == 0)
                                {
                                    tian(i,j,ii,0);
                                    istian = true;
                                }
                            }
                        }
                        else if(f[i][j][0][0] > 1)
                        {
                            if(f[i][j][0][0] < MIN)
                            {
                                MIN = f[i][j][0][0];
                                x = j;
                                y = i;
                                ff = 0;
                            }
                        }
                    }
                    if(z[i][j].y == 0)
                    {
                        if(f[i][j][1][0] == 0)
                        {
                            maodun = true;
                            //printf("*****(%d,%d)矛盾\n", i, j);
                            break;
                        }
                        else if(f[i][j][1][0] == 1)
                        {
                            for(int ii=1;ii<10;++ii)
                            {
                                if(f[i][j][1][ii] == 0)
                                {
                                    tian(i,j,0,ii);
                                    istian = true;
                                }
                            }
                        }
                        else if(f[i][j][1][0] > 1)
                        {
                            if(f[i][j][1][0] < MIN)
                            {
                                MIN = f[i][j][1][0];
                                x = j;
                                y = i;
                                ff = 1;
                            }
                        }
                    }
                }
                else
                {
                    if(z[i][j].x == 0)
                    {
                        if(f[i][j][0][0] == 0)
                        {
                            maodun = true;
                            //printf("*****(%d,%d)矛盾\n", i, j);
                            break;
                        }
                        else if(f[i][j][0][0] == 1)
                        {
                            for(int ii=1;ii<10;++ii)
                            {
                                if(f[i][j][0][ii] == 0)
                                {
                                    tian(i,j,ii,ii);
                                    istian = true;
                                }
                            }
                        }
                        else if(f[i][j][0][0] > 1)
                        {
                            if(f[i][j][0][0] < MIN)
                            {
                                MIN = f[i][j][0][0];
                                x = j;
                                y = i;
                                ff = 0;
                            }
                        }
                    }
                }
            }
            if(maodun)
                break;
        }
        //show();
        if(maodun)
        {
            //printf("返回\n");
            return false;
        }
        if(!istian)
        {
            if(judge()) return true;
            node tz[10][10];
            int tf[10][10][2][10];

            for(int i=0;i<6;++i)
            {
                for(int j=0;j<6;++j)
                {
                    tz[i][j] = z[i][j];
                    for(int k=0;k<2;++k)
                    {
                        for(int m=0;m<10;++m)
                        {
                            tf[i][j][k][m] = f[i][j][k][m];
                        }
                    }
                }
            }
            for(int ii=1;ii<10;++ii)
            {
                if(f[y][x][ff][ii] == 0)
                {
                    //printf("*************假设(%d,%d,%d,%d)\n", y, x, ff, ii);
                    if(y == 3 && x == 1 && ff == 0 && ii == 2)
                        ii = 2;
                    if(ff == 0) tian(y,x,ii,0);
                    else tian(y,x,0,ii);
                    if(solve())
                        return true;
                    for(int i=0;i<6;++i)
                    {
                        for(int j=0;j<6;++j)
                        {
                            z[i][j] = tz[i][j];
                            for(int k=0;k<2;++k)
                            {
                                for(int m=0;m<10;++m)
                                {
                                    f[i][j][k][m] = tf[i][j][k][m];
                                }
                            }
                        }
                    }
                }
            }
            return false;
        }
    }
    return true;
}



int main()
{
    scanf("%d", &T);
    while(T--)
    {
        int CASE;
        scanf("%d", &CASE);
        MS(z, 0);
        MS(f, 0);
        MS(xie, 0);
        for(int i=0;i<6;++i)
        {
            for(int j=0;j<6;++j)
            {
                f[i][j][0][0] = f[i][j][1][0] = 9;
            }
        }
        for(int i=0;i<6;++i)
        {
            for(int j=0;j<6;++j)
            {
                scanf("%s", s);
                int len = strlen(s);
                if(len == 1 && s[0] != '-')
                {
                    tian(i,j,s[0]-'0',s[0]-'0');
                }
                if(len == 3)
                {
                    xie[i][j] = 1;
                    tian(i,j,s[0]=='-'?0:s[0]-'0',s[2]=='-'?0:s[2]-'0');
                }
            }
            int t = 0;
        }
        //show();
        solve();
        printf("%d\n", CASE);
        show();
    }
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值