【HDU2780 - Su-Su-Sudoku】 解題報告+思路+代碼,差點一次AC T^T

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
////#define INPUT
///#define DBG
/**
    Problem: HDU2780 - Su-Su-Sudoku
    Begin Time: 19th/Mar/2012 17:52
    End Time:   19th/Mar/2012 20:04
    Test Data:  基本上樣例過了就過了
    Standard output: See upstair
    Knowledge Point: DFS + 回溯 + 狀態是否合法判斷的一個小Trick
    Thought:
    總體思路就是:在第5個空上挨個填一個數字,如果行的話就輸出,如果不行的話回溯到上一層遞歸試試其他數字。直到所有數字全試完了爲止
                   但是這裏有幾個小tricks
        Trick1:開了一個numOfDigits數組用來記錄1-9每個數字出現了幾次,只有出現小於9次的數字我們才往空裏填,剪枝策略1
        Trick2:開了一個blockState數組,用來判斷每個3x3的小數獨中每個數字是否都出現過,與一個全1數組memcmp比較就可以得到結果了
                不過注意blockState有一個0,所以sucBlock = {0,1,1,1...};
        Trick3:對於大數獨的每行/每列都放入一個數組中排序之後與sucState比較,如果是0,1,2,3,4,5,6,7,8,9則代表符合,否則不符合
                Notice:我們把maze(大數獨)數組的[0]行和[0]列都放棄不用了,所以要有一個前置0
    Experience:
    輸出格式請注意!最後一行不用輸出額外的換行符了,一定要仔細審題!! Presentation Error + 2
    還有數組一定要記得初始化,blockState因爲沒初始化貢獻了WA Wrong Answer + 1
*/
using namespace std;
struct node
{
    int x;
    int y;
};
const int sucBlock[10] = {0,1,1,1,1,1,1,1,1,1};
const int sucState[10] = {0,1,2,3,4,5,6,7,8,9};

int maze[10][10];
node unknowPoint[5];
int numOfDigits[10];
//bool isFound;
int comp(const void* a,const void* b)
{
    return ( *(int*)a - *(int*)b );
}
bool checkBlock(int x,int y)
{
    int blockState[10];
    memset(blockState,0,sizeof(int)*10);
    for(int i = x ; i < x + 3; i++)
    {
        for(int j = y; j < y + 3 ; j++)
        {
            blockState[maze[i][j]]++;
        }
    }
    if( memcmp(blockState,sucBlock,sizeof(int)*10) != 0 )
    {
        return false;
    }
    return true;
}
bool check()
{
#ifdef DBG
    printf("Debuging..Checking this maze :\n");
    for(int i = 1 ; i <= 9 ; i++)
    {
        for(int j = 1 ; j <= 9 ; j++)
        {
            printf("%d ",maze[i][j]);
        }
        printf("\n");
    }
#endif
    int checkState[10];
    for(int i = 1; i <= 9 ; i++)
    {
        ///比較橫行
        memcpy(checkState,maze[i],sizeof(maze[i]));
        qsort(checkState,10,sizeof(int),comp);
        if ( memcmp(checkState,sucState,sizeof(int)*10) != 0 )
        {
            return false;
        }
    }
    checkState[0] = 0;
    for(int i = 1; i <= 9 ; i++)
    {
        ///比較豎行
        for(int j = 1 ; j <= 9 ; j++)
        {
            checkState[j] = maze[j][i];
        }
        qsort(checkState,10,sizeof(int),comp);
        if( memcmp(checkState,sucState,sizeof(int)*10 ) != 0)
        {
            return false;
        }
    }
    for(int i = 1; i <= 7 ; i = i + 3)
    {
        for(int j = 1; j <= 7 ; j = j + 3 )
        {
            if(!checkBlock(i,j))
            {
                return false;
            }
        }
    }
#ifdef DBG
    printf("The res is true\n");
#endif
    return true;
}
bool Solve(int index)
{
    if ( index > 4 )
    {
        return check();
    }
    for( int i = 1; i <= 9 ; i++)
    {
        if( numOfDigits[i] < 9)
        {
            numOfDigits[i]++;
            maze[unknowPoint[index].x][unknowPoint[index].y] = i;
            if ( Solve(index+1) )
            {
                return true;
            }
            maze[unknowPoint[index].x][unknowPoint[index].y] = 0;
            numOfDigits[i]--;
        }
    }
    return false;
}
int main()
{
    int t,k,n;
    char tmp[50];
#ifdef INPUT
    freopen("b:\\acm\\hdu2780\\input.txt","r",stdin);
#ifdef DBG
    freopen("b:\\acm\\hdu2780\\dbg.txt","w",stdout);
#endif
#endif
    while ( scanf("%d",&t) != EOF)
    {
      //  n = 0;    //isFound = false;
       // gets(tmp);
       //scanf("%s",tmp);
        for(k = 0 ; k < t ; k++)
        {
            n = 0;
            memset(maze,0,sizeof(maze));
            memset(tmp,0,sizeof(tmp));
            memset(numOfDigits,0,sizeof(numOfDigits));
            for(int i = 1 ; i <= 9 ; i++)
            {
                scanf("%s",tmp);
                for(int j = 1; j <= 9 ; j++)
                {
                   // scanf("%d",&maze[i][j]);
                    maze[i][j] = tmp[j-1] - '0';
                    if ( maze[i][j] == 0 )
                    {
                        unknowPoint[n].x = i;
                        unknowPoint[n].y = j;
                        n++;
                    }
                    else
                    {
                        numOfDigits[maze[i][j]]++;
                    }
                }
            }
            if ( Solve(0) )
            {
                for(int i = 1 ; i <= 9 ; i++)
                {
                    for(int j = 1 ; j <=9 ; j++)
                    {
                        printf("%d",maze[i][j]);
                    }
                    printf("\n");
                }
            }
            else
            {
                printf("Could not complete this grid.\n");
            }
            if ( k != t - 1 )
            {
                printf("\n");
            }
        }


    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章