洛谷题单指南-进阶搜索-P2324 [SCOI2005] 骑士精神

原题链接:https://www.luogu.com.cn/problem/P2324

题意解读:在5*5棋盘,12个0,12个1,还有一个*,0或1可以和*交换,交换的两个位置必须是类似马走日,给定初始状态,求最少经过多少步可以到达目标状态。

解题思路:要计算最少步数,首先想到BFS,但是由于每一步有8种状态,直接BFS必然超时爆内存。

题目限制在15步之内,可以采用迭代加深方式,再加上启发性剪枝,也就是IDA*算法,才能通过本题。

所谓IDA*算法, 就是在迭代加深的基础上,每次判断当前状态stat已搜索步数和最大步数的关系if(depth > maxdepth) return false时,加入一个估价函数f(stat),f(stat)表示从当前状态stat到达目标状态的最小步数,剪枝变成:

if(depth + f(start) > maxdepth) return false;

这样可以极大减少搜索的状态数。

对于本题,估价函数可以这样设计:统计每个位置与目标位置不同的个数,不考虑*所在位置的不同,因为0/1如果归位了,*自然就归位了。

100分代码:

#include <bits/stdc++.h>
using namespace std;

int t;
/*
目标终点:
11111
01111
00*11
00001
00000
转化成一维:111110111100*110000100000
*/
string target = "111110111100*110000100000";
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};

//估价函数,返回当前状态与目标状态的不同位置的个数
int f(string stat)
{
    int res = 0;
    for(int i = 0; i < 25; i++)
    {
        //只需要考虑24个骑士的位置是否正确,不需要考虑*的位置,因为骑士如果都归位了,*也就归位了
        if(stat[i] != target[i] && stat[i] != '*') res++;
    }
    return res; 
}

// 从start状态开始搜索,当前搜索深度为depth,最大搜索深度为maxdepth
bool dfs(string start, int depth, int maxdepth)
{
    if(depth + f(start) > maxdepth) return false; //剪枝,如果当前深度加上估价函数值大于最大深度,那么就不用继续搜索了
    if(start == target) return true;
    int pos = start.find('*'); //找到*的位置
    int x = pos / 5, y = pos % 5; //计算*的坐标
    for(int i = 0; i < 8; i++)
    {
        int nx = x + dx[i], ny = y + dy[i]; //计算下一个位置
        if(nx < 0 || nx > 4 || ny < 0 || ny > 4) continue;
        int npos = nx * 5 + ny; //计算下一个位置的一维坐标
        string tmp = start;
        swap(tmp[pos], tmp[npos]);
        if(dfs(tmp, depth + 1, maxdepth)) return true;
    }
    return false;
}

int main()
{
    cin >> t;
    while(t--)
    {
        string s, line;
        for(int i = 0; i < 5; i++)
        {
            cin >> line;
            s += line;
        }
        int maxdepth;
        for(maxdepth = 0; maxdepth <= 15; maxdepth++) //迭代加深
        {
            if(dfs(s, 0, maxdepth)) break;
        }
        if(maxdepth <= 15) cout << maxdepth << endl; 
        else cout << -1 << endl;
    }
}

 

posted @   五月江城  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
历史上的今天:
2024-02-19 洛谷题单指南-递推与递归-P1990 覆盖墙壁
2024-02-19 洛谷题单指南-递推与递归-P1164 小A点菜
点击右上角即可分享
微信分享提示