HDU暑假多校第四场J-Let Sudoku Rotate

一、题意

Sudoku is a logic-based, combinatorial number-placement puzzle, which is popular around the world.
In this problem, let us focus on puzzles with 16×16 grids, which consist of 4×4 regions. The objective is to fill the whole grid with hexadecimal digits, i.e. 0123456789ABCDEF, so that each column, each row, and each region contains all hexadecimal digits. The figure below shows a solved sudoku.

考虑一个完成后的数独游戏局面,将16*16的局面分割成4*4的小方块,随机旋转小方块得到一个新的局面,现在给出新的局面,问你最少旋转几次可以得到一个完成的局面。

 

二、解题思路。

首先考虑暴力搜索,4^16次方次旋转——来自每个小方块4次旋转,一共16个小方块。

但是考虑数独游戏的特征,每走一步都可以判断当前的选择是否合法——因此可以进行剪枝——判断下当前所在方块、所在形状的合法性——已经取到的行、列是否合法。

处于某种我证明不了的原因认为,这种方式将会把剪枝操作剪到足够小,以至于31ms就可以搞定1000组输入。

 

 

#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int MAXN=1233;

char mapp[MAXN][MAXN];

int ans=0;

int tran(char c)
{
    if(c>='0'&&c<='9')return c-'0';
    else return c-'A'+10;
}

bool check_left(int a,int b)
{
    // int x = a*4;
    int endd = (b+1)*4;
    if(b == 0)return true;
    for(int i=0;i<4;++i)
    {
        int x = a*4 +i;
        int ch[16];
        memset(ch,0,sizeof(ch));
        for(int j=0;j<endd;++j)
        {
            ch[tran(mapp[x][j])]++;
            if(ch[tran(mapp[x][j])] == 2)return false;
        }
    }return true;
}

bool check_up(int a,int b)
{
    int endd = (a+1)*4;
    if(a == 0)return true;
    for(int j=0;j<4;++j)
    {
        int y = b*4+j;
        int ch[16];
        memset(ch,0,sizeof(ch));
        for(int i=0;i<endd;i++)
        {
            ch[tran(mapp[i][y])]++;
            if(ch[tran(mapp[i][y])] == 2)return false;

        }
    }return true;
}

bool check(int a,int b)
{
    return check_left(a,b)&&check_up(a,b);
}

bool check(int l)
{
    for(int i=0;i<4;++i)
    {
        int x = l*4+i;
        int ch[16];
        memset(ch,0,sizeof(ch));
        for(int j=0;j<16;++j)
        {
            ch[tran(mapp[x][j])]++;
            if(ch[tran(mapp[x][j])]==2)return false;
        }
    }   
    return true;
}

void change(int a,int b)
{
    int x = a*4;
    int y = b*4;

    int tmp = mapp[x][y];
    mapp[x][y] = mapp[x+0][y+3];
    mapp[x+0][y+3] = mapp[x+3][y+3];
    mapp[x+3][y+3] = mapp[x+3][y+0];
    mapp[x+3][y+0] = tmp;

    tmp = mapp[x+0][y+1];
    mapp[x+0][y+1] = mapp[x+1][y+3];
    mapp[x+1][y+3] = mapp[x+3][y+2];
    mapp[x+3][y+2] = mapp[x+2][y+0];
    mapp[x+2][y+0] = tmp;

    tmp = mapp[x+0][y+2];
    mapp[x+0][y+2] = mapp[x+2][y+3];
    mapp[x+2][y+3] = mapp[x+3][y+1];
    mapp[x+3][y+1] = mapp[x+1][y+0];
    mapp[x+1][y+0] = tmp;

    tmp = mapp[x+1][y+1];
    mapp[x+1][y+1] = mapp[x+1][y+2];
    mapp[x+1][y+2] = mapp[x+2][y+2];
    mapp[x+2][y+2] = mapp[x+2][y+1];
    mapp[x+2][y+1] = tmp;

}

void change1(int a,int b)
{
    int x = a*4;
    int y = b*4;

    int tmp = mapp[x][y];
    mapp[x][y] = mapp[x+3][y+0];
    mapp[x+3][y+0] = mapp[x+3][y+3];
    mapp[x+3][y+3] = mapp[x+0][y+3];
    mapp[x+0][y+3] = tmp;

    tmp = mapp[x+0][y+2];
    mapp[x+0][y+2] = mapp[x+1][y+0];
    mapp[x+1][y+0] = mapp[x+3][y+1];
    mapp[x+3][y+1] = mapp[x+2][y+3];
    mapp[x+2][y+3] = tmp;

    tmp = mapp[x+0][y+1];
    mapp[x+0][y+1] = mapp[x+2][y+0];
    mapp[x+2][y+0] = mapp[x+3][y+2];
    mapp[x+3][y+2] = mapp[x+1][y+3];
    mapp[x+1][y+3] = tmp;

    tmp = mapp[x+1][y+1];
    mapp[x+1][y+1] = mapp[x+2][y+1];
    mapp[x+2][y+1] = mapp[x+2][y+2];
    mapp[x+2][y+2] = mapp[x+1][y+2];
    mapp[x+1][y+2] = tmp;



}
bool search(int a,int b,int summ)
{

        // cout<<"search : "<<a<<" "<<b<<" step: "<<summ<<endl;

    if(b==4)
    {
        if(check(a)){
            ans += summ;
            return true;
        }
        return false;
    }

    if(search(a,b+1,summ))return true;
    for(int i=0;i<3;++i)
    {
        change1(a,b);
        if(search(a,b+1,summ+1+i))return true;
    }
    change1(a,b);
    return false;
}

bool dfs(int now,int summ)
{
    int a = now/4;
    int b = now%4;
    if(now == 16)
    {
        ans = min(ans,summ);
        return true;
    }
    if(check(a,b)&&dfs(now+1,summ));
    for(int i=0;i<3;++i)
    {
        change1(a,b);
        if(!check(a,b))continue;
        dfs(now+1,summ+i+1);
    }
    change1(a,b);
    return false;
}


void show()
{
    for(int i=0;i<16;++i)
    {
        for(int j=0;j<16;++j)
        {
            cout<<mapp[i][j];
        }cout<<endl;
    }
}

void init()
{
    ans = INT_MAX;
    for(int i=0;i<16;++i)gets(mapp[i]);
    dfs(0,0);
    cout<<ans<<"\n";
}

int main()
{

    int t;
    // cin>>t;
    scanf("%d\n",&t);
    while(t--)init();

    return 0;
}

 

posted @ 2018-08-02 14:17  六花的邪王真眼  阅读(238)  评论(0编辑  收藏  举报