HDU 6314&&18多校4J 数独 【深度优先搜索】

HDU6314

题意:给一个16*16的只旋转4*4的矩阵的数独,求最少顺时针旋转多少次其中的4*4矩阵能把它还原?

分析:搜索加可行性剪枝即可通过。由于数独限制较强,剪枝效果良好。

 

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=100000;
int ans;
int dx[6],a[6][6][6][6],sx[6],sy[6][6],dy[6];
char s[20][20];
void check(int ii,int x,int y) //翻转0到270度 求出每行每列的值
{
    for(int i=0; i<4; i++)dx[i]=dy[i]=0;
    if(ii==0)
    {
        for(int i=0; i<4; i++)
            for(int j=0; j<=4; j++)
            {
                dx[i]|=a[x][y][i][j];
                dy[j]|=a[x][y][i][j];
            }
    }
    if(ii==1)
    {
        for(int i=0; i<4; i++)
            for(int j=0; j<4; j++)
            {
                dx[j]|=a[x][y][i][j];
                dy[i]|=a[x][y][i][j];
            }
        swap(dy[0],dy[3]);
        swap(dy[1],dy[2]);
    }
    if(ii==2)
    {
        for(int i=0; i<4; i++)
            for(int j=0; j<4; j++)
            {
                dx[i]|=a[x][y][i][j];
                dy[j]|=a[x][y][i][j];
            }
        swap(dx[0],dx[3]);
        swap(dx[1],dx[2]);
        swap(dy[0],dy[3]);
        swap(dy[1],dy[2]);

    }
    if(ii==3)
    {
        for(int i=0; i<4; i++)
            for(int j=0; j<4; j++)
            {
                dx[j]|=a[x][y][i][j];
                dy[i]|=a[x][y][i][j];
            }
        swap(dx[0],dx[3]);
        swap(dx[1],dx[2]);


    }
}
void dfs(int x,int y,int val)
{
    if(x>4)
    {
        ans=min(ans,val);
        return ;
    }
    for(int i=0; i<4; i++)
    {
        check(i,x,y);
        bool flag=true;;
        for(int j=0; j<4; j++)
        {
            if(sx[j]&dx[j]||sy[y][j]&dy[j])
            {
                flag=false;
            }
        }
        if(flag)
        {
            val+=i;
            int tx[5],ty[6];
            for(int j=0; j<4; j++)tx[j]=sx[j],ty[j]=sy[y][j];
            for(int j=0; j<4; j++)
                sx[j]|=dx[j],sy[y][j]|=dy[j];
            if(y==4)
            {
                for(int j=0; j<4; j++)sx[j]=0;
                dfs(x+1,1,val);
            }
            else
                dfs(x,y+1,val);
            for(int j=0; j<4; j++)sx[j]=tx[j],sy[y][j]=ty[j];
            val-=i;
        }
    }
}
int main()
{
    int TA;
    scanf("%d",&TA);
    while(TA--)
    {
        for(int i=1; i<=16; i++)
            scanf(" %s",s[i]+1);

        for(int i=1; i<=4; i++)
            for(int j=1; j<=4; j++)
                for(int k=0,ii=i*4-4+1; ii<=i*4; ii++,k++)
                    for(int l=0,jj=j*4-4+1; jj<=j*4; jj++,l++)
                        if(s[ii][jj]<='9'&&s[ii][jj]>='0')
                            a[i][j][k][l]=(1<<(s[ii][jj]-'0'));
                        else
                            a[i][j][k][l]=(1<<(s[ii][jj]-'A'+10));
        ans=INF;
        memset(sx,0,sizeof(sx));
        memset(sy,0,sizeof(sy));
        dfs(1,1,0);
        printf("%d\n",ans);
    }

}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值