当前位置: 首页 > news >正文

【题解】P2324 [SCOI2005] 骑士精神 [IDA*]

P2324 [SCOI2005] 骑士精神 - 洛谷 (luogu.com.cn)

原来这就叫 IDA* 啊,我之前自己瞎捣鼓也有搞出过这种剪枝。


第一眼好想状态压缩 + bfs,一算状态数:10*3^{25}=8,472,886,094,430

只能从题目限制 15 步下手,考虑深搜 + 剪枝。

步骤:

(0)骑士移动太麻烦,考虑移动空白格

(1)从小到大枚举 0 到 15 步作为最大步 maxdep,用 dfs 验证

(2)dfs 里移动一次空白格为增加一步,如果当前步数比 maxdep 大就退出

(3)当前 maxdep 可以移动成目标棋盘就输出

这样做状态数和 bfs 的差不了多少,但 dfs 有一个很好的点:剪枝够给力

我们给每个状态都计算一个 “完美估价步数” mn(当前状态与目标状态的不相同格子数),

这代表这个状态距离目标状态可能的最少步数

如果当前步数 + 最少步数 mn > maxdep,那么剪枝。

不过还有个细节:

因为移动的是空白格,只有在最后一步才有可能一步消除 2 的差异,其他时候一步最多只能消除 1 的差异,所以非 0 差异数 - 1。

这样就能严格保证估价 >= 实际花费。

还有个剪枝,在搜索到正解后 flag = 1,其他分支直接退出。

还有往回移动,这也可以剪掉。

时间复杂度很难算,我们可以从最坏角度考虑:

根据模拟情况,粗略估计每轮剪掉 5 个支(实际上 15 轮平均每轮剪 6 ~ 7 个)无解数据的状态数:3 ^ 15 = 14,348,907还有两个剪枝没算进去,实际上小得多最坏情况(10 组无解数据):操作次数量级最大在 1e8 左右

实际上,这种提前计算未来代价的剪枝,就叫做 IDA* 算法

常用于 dfs 剪枝中,常见形式为:

记录到达当前结点 x 的实际成本 g(x),并利用它到终点的最小成本估计 h(x) 进行剪枝。

设 f(x) = g(x) + h(x),如果 f(x) 超过阈值 C,则停止对该分支的搜索。

代码:

#include<bits/stdc++.h>
using namespace std;char s[7][7];
int mat[7][7], a[7][7];
int goal[7][7] = {{0, 0, 0, 0, 0, 0},{0, 1, 1, 1, 1, 1},{0, 0, 1, 1, 1, 1},{0, 0, 0, 2, 1, 1},{0, 0, 0, 0, 0, 1},{0, 0, 0, 0, 0, 0}
};
int mxdep;
int dx[8] = {-2, -2, -1, 1, 2, 2, 1, -1};
int dy[8] = {-1, 1, 2, 2, 1, -1, -2, -2};
int anti[9] = {4, 5, 6, 7, 0, 1, 2, 3, -1};
bool flag;int get_eva() {int sum = 0;for (int i = 1; i <= 5; i ++) {for (int j = 1; j <= 5; j ++) {if (mat[i][j] != goal[i][j]) {sum ++;}}}return (sum == 0)? 0 : sum - 1;
}void dfs(int x, int y, int dep, int last) {if (flag) {return ;}if (dep == mxdep) {if (get_eva() == 0) {flag = 1;}return ;}for (int i = 0; i <= 7; i ++) if (i != anti[last]) {int xx = x + dx[i], yy = y + dy[i];if (xx >= 1 && xx <= 5 && yy >= 1 && yy <= 5) {swap(mat[x][y], mat[xx][yy]);int mn = get_eva();if (mn == 0) {flag = 1;return ;}if (mn + dep + 1 <= mxdep) {dfs(xx, yy, dep + 1, i);}swap(mat[x][y], mat[xx][yy]);}}
}int main () {ios::sync_with_stdio(false);cin.tie(0);int T; cin >> T;while (T --) {int x = 0, y = 0;for (int i = 1; i <= 5; i ++) {cin >> (s[i] + 1);for (int j = 1; j <= 5; j ++) {if (s[i][j] == '*') {mat[i][j] = 2;x = i; y = j;} else {mat[i][j] = s[i][j] - '0';}a[i][j] = mat[i][j];}}for (int i = 0; i <= 15; i ++) {flag = 0;mxdep = i;memcpy(mat, a, sizeof(a));dfs(x, y, 0, 8);if (flag) {cout << i << "\n";break;}}if (flag == 0) {cout << "-1\n";}}return 0;
}

http://www.dtcms.com/a/619525.html

相关文章:

  • 杭州自助建站网站网站变灰代码 所有浏览器
  • 中国建设银行官网站积分抽奖网站浮窗制作
  • 网站建设四网合一app开发与网站开发的区别
  • Leetcode 55
  • 网站上百度要怎么做的营销网名大全
  • 网站建设 淘宝运营公司网站怎么做啊
  • 研发网站要多久小男生和大人做的网站
  • Python数据分析 -- Pandas基础入门学习笔记:从核心概念到实操代码
  • 怎么在淘宝上做网站wordpress 文章 形式
  • Deap、Seed和Seed4心电数据集详细介绍(附下载链接)
  • 网站LOGO透明底色PNG格式怎么做的wordpress建图片站
  • 工业互联网中的AI与大数据:推动智能化决策的力量
  • 网站为什么百度不收录信誉好的顺德网站建设
  • 西安有哪些网站建设外包公司长沙装修公司电话
  • 一个网站的设计思路wordpress主题侧边栏
  • wordpress站群版丹东市市政建设总公司
  • 【核心完整复现】【DRCC】考虑N-1准则的分布鲁棒机会约束低碳经济调度
  • 推动门户网站建设不断优化升级wordpress wcps
  • Wooldridge《多Agent系统引论》:知识体系全景
  • 软件体系结构——基本架构演变
  • 做网站首页代码百度正版下载并安装
  • 做评测好的视频网站有哪些格尔木网站建设公司
  • 设计大型网站建设网站合作建设方案
  • 国际域名网站怎么样做英文网站
  • 兰溪市网站建设公司做公司网站需要多
  • 品牌建设网站例子公众号开发哪家专业
  • 学习FreeRTOS(first day)
  • 体育西网站开发设计网站营销怎么做
  • 东营做网站tt0546建筑材料东莞网站建设
  • 学会使用搜索引擎的日期筛选功能