数独问题

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define          N          9
#define     SET_BIT(x,b)    x |= ((1 << b)&0xFF)
#define     USET_BIT(x,b)   x &= ~(1 << b)
#define     RD_BIT(x,b)     x&(1 << b)


// 测试用例1
char box1[N*N]     = ".........963278541254961378547612839192387456386549127675893214421756983839124765";
char box1_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";

// 测试用例2

char box2[N*N]     = "...435692...278541...961378547612839192387456386549127675893214421756983839124765";
char box2_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";

char box3[N*N]     = ".18435692.63278541.54961378.47612839.92387456.86549127.75893214.21756983.39124765";
char box3_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";

char box4[N*N]     = ".18439992963278541254961378547612839192387456386549127675893214421756983839124765";
char box4_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";

char box5[N*N]     = "63...12....5.3..71.41..9.36.1.68.9.....14..8.384...1..8.6.1.3.51.93.8..2...5.2.1.";
char box5_out[N*N] = "638471259295836471741259836517683924962147583384925167826714395159368742473592618";
char box6[N*N]     = "....3..9....2....1.5.9..............1.2.8.4.6.8.5...2..75......4.1..6..3.....4.6.";
char box6_out[N*N] = "718435692963278541254961378547612839192387456386549127675893214421756983839124765";


//char last[N*N];

/* 根据当前坐标,计算出相邻8个格子坐标的差值 */
char near[][8] = {{1, 2, 9, 10, 11, 18, 19, 20}, {-1, 1, 8, 9, 10, 17, 18, 19},
                   {-2, -1, 7, 8, 9, 16, 17, 18}, {-9, -8, -7, 1, 2, 9, 10, 11},
                   {-10, -9, -8, -1, 1, 8, 9, 10}, {-11, -10, -9, -2, -1, 7, 8,
                   9}, {-18, -17, -16, -9, -8, -7, 1, 2},
                   {-19, -18, -17, -10, -9, -8, -1, 1},
                   {-20, -19, -18, -11, -10, -9, -2, -1}};

 

void pp(char a[N])
{
    int i, j;

    for (j = 0;j < N;++j)
    {
        for (i = 0;i < N;++i)
        {
            printf("%c ", a[j*N+i]);
        }
        printf("/n");
    }
    printf("/n");
}

int index(x)
{
    int i = 0;
    x = x % 27;
    i = x%3 + x/9*3;
}

int check(char a[], int x)
{
    int i, j, k;
    int bits = 0xFF;
   
    USET_BIT(bits, a[x] - '0');
//    printf("check 1/n"); /* 检查x所属小单元里面是1~9 */
    for (i = 0, j = index(x);i < 8;++i)
    {
        k = x + near[j][i];
        if (a[k] == '0'||a[k] == '.') continue;

        if (a[k] == a[x])
        {
//            printf("a[%d] == a[%d]/n", k, x);
            return 0;
        }
    }

//    printf("check 2/n"); /* 检查每一行是1~9 */
    for (i = x/9*9;i < x/9*9+9;++i)
    {
        if (i == x)
            continue;

        if (a[i] == a[x])
        {
//            printf("a[%d] == a[%d]/n", i, x);
            return 0;
        }
    }

//    printf("check 3/n"); /* 检查每一列是1~9 */
    for (i = x%9;i < 81;i += 9)
    {
        if (i == x)
            continue;

        if (a[x] == a[i])
        {
//            printf("a[%d] == a[%d]/n", i, x);
            return 0;
        }
    }

    return 1;
}

/* 计算出结果返回1, 没有解返回0 */
int compute(char *arr)
{

    int  i = 0, j = 0;
    char last[N*N] = {0}; // 回溯的状态

    for (i = 0;i < N*N;++i)
        if ('.' != arr[i])
            last[i] = '*';
        else
            last[i] = '0';

    i = 0;
    while (i >= 0)
    {
        if ('*' == last[i])
        {
            ++i;
            continue;
        }

        if (i >= 81)
        {
            for (j = 0;j < 81;++j)
            {
                if (!check(arr, j))
                    return 0;
            }
            return 1;
        }
        arr[i] = last[i] + 1;
        while (arr[i] <= '9')
        {
            if (!check(arr, i))
            {
                ++arr[i];
            }
            else
            {
                if (i == 80)
                {
                    return 1;
//                    printf("out: =====================================/n");
//                    pp(arr);
                    //                  getchar();
                    arr[i] = '9' + 1;
                }
                break;
            }
        }

        if (arr[i] > '9')
        {
            last[i] = '0';
            arr[i] = '0';
            --i;
            while ('*' == last[i])
            {
                --i;
            }
            continue;
        }

        /* pp(arr); */
        /* getchar(); */
       
        last[i] = arr[i];
        ++i;
    }

    return 0;
}

int main()
{
    int i, j;

    /* for (j = 0;j < N;++j) */
    /* { */
    /*     for (i = 0;i < N;++i) */
    /*     { */
    /*         scanf("%c", arr[j][i]);  */
    /*     } */
    /* } */

    /* for (i = 0;i < 81;++i) */
    /* { */
    /*     printf("%d %d/n", i, index(i)); */
    /* } */

    printf("----------test1---------/n");
    pp(box1);
    if (compute(box1))
    {
        assert(strncmp(box1, box1_out, N*N) == 0);
        pp(box1);
    }
    else
        printf("NO Answer!/n");

    printf("----------test2---------/n");
    pp(box2);
    if (compute(box2))
    {
        assert(strncmp(box2, box2_out, N*N) == 0);
        pp(box2);
    }
    else
        printf("NO Answer!/n");

    printf("----------test3---------/n");
    pp(box3);
    if (compute(box3))
    {
        assert(strncmp(box3, box3_out, N*N) == 0);
        pp(box3);
    }
    else
        printf("NO Answer!/n");
   
    printf("----------test4---------/n");
    pp(box4);
    if (compute(box4))
    {
        assert(strncmp(box4, box4_out, N*N) == 0);
        pp(box4);
    }
    else
        printf("NO Answer!/n");

    printf("----------test5---------/n");
    pp(box5);
    if (compute(box5))
    {
        assert(strncmp(box5, box5_out, N*N) == 0);
        pp(box5);
    }
    else
        printf("NO Answer!/n");
   
    printf("----------test6---------/n");
    pp(box6);
    if (compute(box6))
    {
        assert(strncmp(box6, box6_out, N*N) == 0);
        pp(box6);
    }
    else
        printf("NO Answer!/n");

    return 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值