HDU-2234 无题I(IDA*)

28 篇文章 0 订阅


无题I

Time Limit: 10000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
一天机器人小A在玩一个简单的智力游戏,这个游戏是这样的,在一个4*4的矩阵中分别有4个1,4个2,4个3和4个4分别表示4种不同的东西,每一步小A可以把同一行的4个数往左移或者往右移一步或者把同一列的4个数字往上移或者往下移一步(1,2,3,4往左移后是2,3,4,1),小A现在想知道进过最少的几步移动可以将矩阵的每行上的4个数字都一样或者每列上的4个数字都一样。但是小A又不想走太多步,他只要知道最少步数是否少于等于5步,是的话输出准确的步数,否则输出-1。
 

Input
先输入一个整数T,表示有T组数据。
对于每组数据输入4行,每行4列表示这个矩阵。
 

Output
对于每组输入输出一个正整数表示最少的移动步数,大于5则输出-1.
 

Sample Input
  
  
2 1 2 3 4 1 2 3 4 1 2 3 4 2 3 4 1 4 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4
 

Sample Output
  
  
1 1


和HDU-1667  The Rotation Game 一样都是通过旋转的方式进行游戏,所以直接把代码改了一下就交了(原谅懒癌)

做题时强行不认真读题,2次理解错题意,WA,其实只用更改剪枝的函数,其他基本一样。

惊讶的是第一次就904ms,突然就进入前20,看到以前的大神优化好久才进入2000ms,一定是数据变水了或者hdu升级了



#include <cstdio>
#include <algorithm>

using namespace std;

int mp[5][5],an,step,depth,tmp,tp[5],tt[5],t;

void Judge() {//算出最多有多少个数字在正确的位置上
    int i,j;
    an=t=0;
    for(i=0;i<4;++i) {
        tp[1]=tp[2]=tp[3]=tp[4]=0;
        tt[1]=tt[2]=tt[3]=tt[4]=0;
        for(j=0;j<4;++j) {
            ++tp[mp[i][j]];
            ++tt[mp[j][i]];
        }
        an+=max(max(tp[1],tp[2]),max(tp[3],tp[4]));//行的情况
        t+=max(max(tt[1],tt[2]),max(tt[3],tt[4]));//列的情况
    }
    an=max(an,t);
}

inline void RatColU(int c) {
    tmp=mp[0][c];
    mp[0][c]=mp[1][c];
    mp[1][c]=mp[2][c];
    mp[2][c]=mp[3][c];
    mp[3][c]=tmp;
}

inline void RatColD(int c) {
    tmp=mp[3][c];
    mp[3][c]=mp[2][c];
    mp[2][c]=mp[1][c];
    mp[1][c]=mp[0][c];
    mp[0][c]=tmp;
}

inline void RatRowL(int r) {
    tmp=mp[r][0];
    mp[r][0]=mp[r][1];
    mp[r][1]=mp[r][2];
    mp[r][2]=mp[r][3];
    mp[r][3]=tmp;
}

inline void RatRowR(int r) {
    tmp=mp[r][3];
    mp[r][3]=mp[r][2];
    mp[r][2]=mp[r][1];
    mp[r][1]=mp[r][0];
    mp[r][0]=tmp;
}

void (*Rat[16])(int)={RatColU,RatColU,RatColU,RatColU,RatRowR,RatRowR,RatRowR,RatRowR,RatColD,RatColD,RatColD,RatColD,RatRowL,RatRowL,RatRowL,RatRowL};
const int num[16]={0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3};

bool DFS() {
    Judge();
    if(an==16)
        return true;
    if(step+(19-an)/4>depth)//如果当前已走步数加上至少要走的步数大于深搜的深度则返回false
        return false;       //至少要走的步数除以4是因为每次旋转可改变四个位置,即最多可让四个数走到正确位置
                            //19=16+3是为了向上取整
    int i=0;
    for(;i<8;++i) {
        Rat[i](num[i]);
        ++step;
        if(DFS())
            return true;
        --step;
        Rat[i+8](num[i]);
    }
    for(;i<16;++i) {
        Rat[i](num[i]);
        ++step;
        if(DFS())
            return true;
        --step;
        Rat[i-8](num[i]);
    }
    return false;
}

int main() {
    int i,j,T;
    scanf("%d",&T);
    while(T--) {
        for(i=0;i<4;++i)
            for(j=0;j<4;++j)
                scanf("%d",&mp[i][j]);
        step=0;
        depth=1;
        while(!DFS()) {
            if(++depth>5)
                break;
        }
        printf("%d\n",depth>5?-1:step);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值