1. 程式人生 > >20. 帶旋轉的數獨遊戲

20. 帶旋轉的數獨遊戲

Description

數獨是一個基於邏輯的組合數字放置拼圖,在世界各地都很受歡迎。
在這個問題上,讓我們關注

#include <vector>
#include <cstdio>//
#include <algorithm>
#include <climits>
#include <cstring>//
using namespace std;

char mp[18][18];
char mp1[18][18];
int rot[4][4];//大的16個正方形區域
char rotb[4][4];//小的備用旋轉用的4*4方塊
int c[16];
char x[16];
int flag = 0;
int check_hang(int u);
int dfs(int u, int v);
int rotation(int n, int x, int y);
int huifu(int x, int y);
int check_lie(int u);

int check_hang(int u){//check裡面的u代表小行行數,滿足返回1,不滿足返回0
    for (int i = 0; i < 16; i++){
        switch(mp[u][i]){
            case '0': c[0]++; break;
            case '1': c[1]++; break;
            case '2': c[2]++; break;
            case '3': c[3]++; break;
            case '4': c[4]++; break;
            case '5': c[5]++; break;
            case '6': c[6]++; break;
            case '7': c[7]++; break;
            case '8': c[8]++; break;
            case '9': c[9]++; break;
            case 'A': c[10]++; break;
            case 'B': c[11]++; break;
            case 'C': c[12]++; break;
            case 'D': c[13]++; break;
            case 'E': c[14]++; break;
            case 'F': c[15]++; break;
        }
    }
    for(int i = 0; i < 16; i++){
        if(c[i] == 0 || c[i] > 1){
            memset(c, 0, sizeof(c));
            return 0;
        }
    }
    memset(c, 0, sizeof(c));
    return 1;
}
int dfs(int u, int v){//u代表dfs的大行行數(1開始), v代表旋轉的是第幾個方塊
    //遞迴終止條件
    if(flag == 1)
        return 0;
    if(v == 4){
        for(int i = 0; i < 4; i++){
            rotation(i, u, v);
            if(check_hang((u - 1) * 4) == 1){
                flag = 1;
                return 0;
            }
            else{
                huifu(u, v);
                rot[u - 1][v - 1] = 0;
            }
        }
    }
    else{
        for (int i = 0; i < 4; i++){
            rotation(i, u, v);
            dfs(u, v + 1);
            if(check_hang((u-1)*4) == 1){
                flag = 1;
                return 0;
            }
            else{
                huifu(u, v);
            }
        }
    }
    return 0;
}
int rotation(int n, int x, int y){//n代表旋轉幾次(從0開始),x代表大行行數(從1開始)y代表第幾個方塊(從1開始)
    for (int i = 0; i < n; i++){
        for (int j = 3; j >= 0; j--){
            for (int k = 0; k < 4; k++){
                rotb[3 - j][k] = mp[k+(x-1)*4][j+(y-1)*4];
            }
        }
        for (int jj = 0; jj < 4; jj++){//把rotb賦值給mp
            for (int kk = 0; kk < 4; kk++){
                mp[jj + (x - 1) * 4][kk + (y - 1) * 4] = rotb[jj][kk];
            }
        }
    }
    rot[x - 1][y - 1] = n;
    return 0;
}
int huifu(int x, int y){
    for (int i = 0; i < 4; i++){
        for (int j = 0; j < 4; j++){
            mp[(x - 1) * 4 + i][(y - 1) * 4 + j] = mp1[(x - 1) * 4 + i][(y - 1) * 4 + j];
        }
    }
    return 0;
}

int check_lie(){
    for (int i = 0; i < 16; i++){
        switch(x[i]){
            case '0': c[0]++; break;
            case '1': c[1]++; break;
            case '2': c[2]++; break;
            case '3': c[3]++; break;
            case '4': c[4]++; break;
            case '5': c[5]++; break;
            case '6': c[6]++; break;
            case '7': c[7]++; break;
            case '8': c[8]++; break;
            case '9': c[9]++; break;
            case 'A': c[10]++; break;
            case 'B': c[11]++; break;
            case 'C': c[12]++; break;
            case 'D': c[13]++; break;
            case 'E': c[14]++; break;
            case 'F': c[15]++; break;
        }
    }
    for(int i = 0; i < 16; i++){
        if(c[i] == 0 || c[i] > 1){
            memset(c, 0, sizeof(c));
            return 0;
        }
    }
    memset(c, 0, sizeof(c));
    return 1;
}

    int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        flag = 0;
        for (int i = 0; i < 16; i++){
            scanf("%s", &mp[i]);
            for (int j = 0; j < 16; j++){
                mp1[i][j] = mp[i][j];
            }
        }
        for (int i = 1; i < 5; i++){//此時i代表大行的行數(從1開始)
            flag = 0;
            dfs(i, 1);
        }

        for (int i1 = 0; i1 < 2; i1++)
        {
           
            for (int i2 = 0; i2 < 2; i2++)
            {
               
                for (int i3 = 0; i3 < 2; i3++)
                {
                    
                    for (int i4 = 0; i4 < 2; i4++)
                    {   
                        x[0] = mp[0][0+i1*3];
                        x[1] = mp[1][0+i1*3];
                        x[2] = mp[2][0+i1*3];
                        x[3] = mp[3][0+i1*3];
                        x[4] = mp[4][0+i2*3];
                        x[5] = mp[5][0+i2*3];
                        x[6] = mp[6][0+i2*3];
                        x[7] = mp[7][0+i2*3];
                        x[8] = mp[8][0+i3*3];
                        x[9] = mp[9][0+i3*3];
                        x[10] = mp[10][0+i3*3];
                        x[11] = mp[11][0+i3*3];
                        x[12] = mp[12][0+i4*3];
                        x[13] = mp[13][0+i4*3];
                        x[14] = mp[14][0+i4*3];
                        x[15] = mp[15][0+i4*3];
                        if(check_lie() == 1)
                            goto p;
                        for (int m = 0; m < 4; m++){
                                rot[3][m] = (rot[3][m] + 2) % 4;
                            }
                    }
                    for (int m = 0; m < 4; m++){
                                rot[2][m] = (rot[2][m] + 2) % 4;
                            }
                }
                for (int m = 0; m < 4; m++){
                                rot[1][m] = (rot[1][m] + 2) % 4;
                            }
            }
            for (int m = 0; m < 4; m++){
                                rot[0][m] = (rot[0][m] + 2) % 4;
                            }
        }

    p:
        int total = 0, total1 = 0;
        for (int i = 0; i < 4; i++)
            for (int j = 0; j < 4; j++){
                total = rot[i][j] + total;
                total1 = (rot[i][j] + 2) % 4 + total1;
            }

        if(total < total1){
            printf("%d\n", total);
            for (int i = 0; i < 4;i++){
                for (int j = 0; j < 4;j++){
                    for (int k = 0; k < rot[i][j];k++){
                        printf("%d %d\n", i+1, j+1);
                    }
                }
            }
        }
        
        else
        {
            printf("%d\n", total1);
            for (int i = 0; i < 4;i++){
                for (int j = 0; j < 4;j++){
                    for (int k = 0; k < (rot[i][j]+2)%4;k++){
                        printf("%d %d\n", i+1, j+1);
                    }
                }
            }
        }
        
                

                /*putchar('\n');
        //輸出
        for (int i = 0; i < 16; i++){
            for (int j = 0; j < 16;j++){
                putchar(mp[i][j]);
            }
            putchar('\n');
        }
        putchar('\n');*/
                
    }
    return 0;
}