• 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<<"
    ";
    }
    
    int main()
    {
    
        int t;
        // cin>>t;
        scanf("%d
    ",&t);
        while(t--)init();
    
        return 0;
    }
  • 相关阅读:
    多轨车皮编序问题
    [Luogu1032] 字串变换
    [POJ1101] The Game
    Linux 下源码编译FFMEG
    交叉编译 tcpdump
    现代电视原理-电视传像原理
    Dos:‘锘緻echo’ 不是内部或外部命令,也不是可运行的程序或批处理文件
    Win7 登入壁纸修改
    Office 2016安装后的优化设置
    Linux 系统目录结构
  • 原文地址:https://www.cnblogs.com/rikka/p/9406882.html
Copyright © 2020-2023  润新知