HDU-2234 无题I

为每个状态定义两个函数S和H,分别表示当前状态到列一致和行一致的目标状态的最少操作次数。

然后有了估价函数F=Min(S,H)就可以IDA*了。

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>

#define rep(i, l, r) for(int i=l; i<=r; i++)
#define down(i, l, r) for(int i=l; i>=r; i--)
#define maxn 40320
#define MAX 1<<30

using namespace std;

int t, n[5][5], k;

inline void Up(int x) { int a; a = n[1][x]; n[1][x] = n[2][x]; n[2][x] = n[3][x]; n[3][x] = n[4][x]; n[4][x] = a; }
inline void Down(int x) { int a; a = n[4][x]; n[4][x] = n[3][x]; n[3][x] = n[2][x]; n[2][x] = n[1][x]; n[1][x] = a; }
inline void Right(int x) { int a; a = n[x][4]; n[x][4] = n[x][3]; n[x][3] = n[x][2]; n[x][2] = n[x][1]; n[x][1] = a; }
inline void Left(int x) { int a; a = n[x][1]; n[x][1] = n[x][2]; n[x][2] = n[x][3]; n[x][3] = n[x][4]; n[x][4] = a; }

int S()
{
    int b[5], o, o2 = 0;
    rep(i, 1, 4) 
    {
        rep(j, 1, 4) b[j] = 0; o = 0;
        rep(j, 1, 4) b[n[j][i]]++;
        rep(j, 1, 4) o = max(o, b[j]);
        o2 = max(o2, 4-o);
    }
    return o2;
}

int H()
{
    int b[5], o, o2 = 0;
    rep(i, 1, 4) 
    {
        rep(j, 1, 4) b[j] = 0; o = 0;
        rep(j, 1, 4) b[n[i][j]]++;
        rep(j, 1, 4) o = max(o, b[j]);
        o2 = max(o2, 4-o);
    }
    return o2;
}

bool Search(int x)
{
    if (x == k)
    {
        if (!S() || !H()) return true; else return false;
    }
    int now = min(S(), H()); if (now > k-x) return false;
    Left(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(1);
    Left(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(2);
    Left(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(3);
    Left(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(4);
    Right(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(1);
    Right(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(2);
    Right(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(3);
    Right(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(4);
    Up(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(1);
    Up(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(2);
    Up(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(3);
    Up(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(4);
    Down(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(1);
    Down(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(2);
    Down(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(3);
    Down(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(4);
    return false;
}

int main()
{ 
    scanf("%d", &t);
    while (t--)
    {
        rep(i, 1, 4) rep(j, 1, 4) scanf("%d", &n[i][j]);
        k = 0;
        while (k <= 5)
            if (Search(0)) break; else k++;
        if (k == 6) k = -1; printf("%d\n", k);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/NanoApe/p/4316710.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值