[SCOI2005]骑士精神【迭代加深+IDA*】

题目链接 P2324 [SCOI2005]骑士精神


首先,我们先讲讲几个基础知识:

迭代加深

  我们假设深度优先搜索(DFS)的最深搜索到Max_depth,那么也就是说深度到达Max_depth的时候不管满不满足答案都要返回了true or false。

IDA*启发式搜索优化DFS

  作为A*算法,也就是有估值函数这样的定义了,原来的深度小于等于Max_depth也将剪枝成为当前的深度deep(表示已经走的路程)+至少需要再走的路程(估值)要小于等于Max_depth才可以走,这就是启发式的思想了。

估值函数

  这里的估值函数肯定是“差距”了,当然是偏小的,不过这没有关系。

inline int _Det()
{
    int sum = 0;
    for(int i=0; i<5; i++) for(int j=0; j<5; j++) if(a[i][j] ^ Bas[i][j]) sum++;
    return sum;
}

启发式搜索

bool dfs(int x, int y, int deep, int Lim_depth)
{
    if(deep == Lim_depth && !_Det()) return true;
    else if(deep == Lim_depth) return false;
    for(int i=0, xx, yy; i<8; i++)
    {
        xx = x + dir[i][0]; yy = y + dir[i][1];
        if(!In_Map(xx, yy)) continue;
        swap(a[x][y], a[xx][yy]);
        if(deep + _Det() <= Lim_depth && dfs(xx, yy, deep + 1, Lim_depth)) return true; //at last turn one exchange tuo
        swap(a[x][y], a[xx][yy]);
    }
    return false;
}

  这里的判断条件是“deep + _Det() <= Lim_depth”是因为最后一次移动,可能一次性会改变两个值,所以本身应该是“deep + 1 + _Det() - 1 <= Lim_depth”。

Code

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
#define MAX_3(a, b, c) max(a, max(b, c))
#define MAX_4(a, b, c, d) max(max(a, b), max(c, d))
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int Bas[5][5] =
{
    1, 1, 1, 1, 1,
    0, 1, 1, 1, 1,
    0, 0, 2, 1, 1,
    0, 0, 0, 0, 1,
    0, 0, 0, 0, 0
};
const int dir[8][2] =
{
    -1, -2,
    -1, 2,
    1, -2,
    1, 2,
    -2, -1,
    -2, 1,
    2, -1,
    2, 1
};
inline bool In_Map(int x, int y) { return x >= 0 && y >= 0 && x < 5 && y < 5; }
char mp[5][5];
int a[5][5];
inline int _Det()
{
    int sum = 0;
    for(int i=0; i<5; i++) for(int j=0; j<5; j++) if(a[i][j] ^ Bas[i][j]) sum++;
    return sum;
}
bool dfs(int x, int y, int deep, int Lim_depth)
{
    if(deep == Lim_depth && !_Det()) return true;
    else if(deep == Lim_depth) return false;
    for(int i=0, xx, yy; i<8; i++)
    {
        xx = x + dir[i][0]; yy = y + dir[i][1];
        if(!In_Map(xx, yy)) continue;
        swap(a[x][y], a[xx][yy]);
        if(deep + _Det() <= Lim_depth && dfs(xx, yy, deep + 1, Lim_depth)) return true; //at last turn one exchange tuo
        swap(a[x][y], a[xx][yy]);
    }
    return false;
}
int main()
{
    int T; scanf("%d", &T);
    while(T--)
    {
        for(int i=0; i<5; i++)
        {
            scanf("%s", mp[i]);
            for(int j=0; j<5; j++)
            {
                a[i][j] = mp[i][j] == '*' ? 2 : mp[i][j] - '0';
            }
        }
        if(!_Det()) { printf("0\n"); continue; }
        int sx = 0, sy = 0;
        for(int i=0; i<5; i++) for(int j=0; j<5; j++)
        {
            if(a[i][j] == 2) { sx = i; sy = j; break; }
        }
        bool flag = false;
        for(int i=1; i<=15; i++)
        {
            if(dfs(sx, sy, 0, i))
            {
                flag = true; printf("%d\n", i);
                break;
            }
        }
        if(!flag) printf("-1\n");
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值