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;
}

时间: 2024-10-15 21:24:46

HDU-2234 无题I的相关文章

HDU 2236 无题II(二分图匹配+二分)

HDU 2236 无题II 题目链接 思路:行列只能一个,想到二分图,然后二分区间长度,枚举下限,就能求出哪些边是能用的,然后建图跑二分图,如果最大匹配等于n就是符合的 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 105; int t, n, x[N][N], have[N]

HDU ACM 2234 无题I-&gt;IDA*算法

分析:IDA*解决,借鉴大牛的启发式函数h(): 可以考虑把每一行上的数转化成相同的,或者把每一列上的数字转化成相同的,二者取最小值. 例如: 1 1 3 2 2 4 4 2 3 3 1 4 1 2 3 4 把这个矩阵转化成行合法矩阵需要的操作:第一行至少要2次,第二行也是2次, 第三行是2次,第四行是3次, 所以把矩阵转化成行相同至少要3次. #include<iostream> using namespace std; int map[5][5]; int deep; #define ma

Hdu 2236 无题II 最大匹配+二分

题目链接: Hdu 2236 解题思路: 将行和列理解为二分图两边的端点,给出的矩阵即为二分图中的所有边, 如果二分图能完全匹配,则说明 不同行 不同列的n个元素 区间为(min_edge,max_edge),这些edge是指构成完全匹配的那些边 题目需要求解最小区间长度 我们 可以 二分区间长度(0~100),每次枚举区间的下界 最后得到的maxl 即为答案 代码: #include<iostream> #include<cstdio> #include<cstring&g

HDU 专题分类

[背包问题] 2602 Bone Collector 1114 Piggy-Bank 1203 I NEED A OFFER! 1171 Big Event in HDU 1059 Dividing 2844 Coins 2191 悼念512汶川大地震遇难同胞--珍惜现在,感恩生活 2159 FATE 1561 The more, The Better 1011 Starship Troopers 2639 Bone Collector II 3033 I love sneakers! 2955

【图论】二分图匹配总结

二分图匹配总结 二分图匹配 1.二分图最大匹配.求两个集合内,每一个元素仅仅能用一次.两集合间存在一些匹配关系,求最大匹配多少对,利用匈牙利算法,对于每一个结点不断去找增广路去匹配 有几个重要性质: 1.最小点覆盖 = 最大匹配 2.最大独立集 = 总结点 - 最大匹配 模板: bool dfs(int u) { for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (vis[v]) continue; vis[v] = 1; i

hdu 无题II(二分差值+最大匹配)

http://acm.hdu.edu.cn/showproblem.php?pid=2236 找n个数使得这n个数都在不同的行和列里显然是二分图模型.难点在于求最大值与最小值差值最小.这里二分差值(看的题解),进行试探是否可以匹配成功. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.

BNUOJ 6378 无题I

无题I Time Limit: 10000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 223464-bit integer IO format: %I64d      Java class name: Main 一天机器人小A在玩一个简单的智力游戏,这个游戏是这样的,在一个4*4的矩阵中分别有4个1,4个2,4个3和4个4分别表示4种不同的东西,每一步小A可以把同一行的4个数往左移或者往右移一

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

HDU——PKU题目分类

HDU 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 1049 1050 1057 1062 1063 1064 1070 1073 1075 1082 1083 1084 1088 1106 1107 1113 1117 1119 1128 1129 1144 1148 1157 1161 1170 1172 1177 1197 1200 1201

HDU 3605 Escape(状压+最大流)

Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 9430    Accepted Submission(s): 2234 Problem Description 2012 If this is the end of the world how to do? I do not know how. But now scient