UVa1063/LA3807 The Rotation Game

UVa1063/LA3807 The Rotation Game

  • 题目链接
  • 题意
    • 输入格式
    • 输出格式
  • 分析
  • AC 代码
    • IDA*
    • 分3次BFS

题目链接

  本题是2004年icpc亚洲区域赛上海赛区的H题

题意

  如下图所示形状的棋盘上分别有8个1、2、3,要往A~H方向旋转棋盘,使中间8个方格数字相同。图(a)进行A操作后变为图(b),再进行C操作后变为图(c),这正是一个目标状态(因为中间8个方格数字相同)。要求旋转次数最少。如果有多解,操作序列的字典序应尽量小。
The Rotation Game

输入格式

  输入包括不超过 30 组测试数据。每个测试数据只包括一行,包含 24 个整数,每相邻两个整数之间用 1 个空格隔开,表示这个 “#” 形棋盘的初始状态。(这些整数的排列顺序是从上至下,同一行的从左至右。)每两组测试数据之间没有换行符。输入文件以一行 0 结束。

输出格式

  对于每组测试数据,输出两行。第一行用字符 A∼H 输出操作的方法,每两个操作字符之间没有空格分开,如果不需要任何步数,输出 No moves needed。第二行输出最终状态中最中间的 8 个格子里的数字。如果有多组解,输出操作次数最少的一组解;如果仍有多组解,输出字典序最小的一组。任意相邻两组测试数据的输出之间不需输出换行符。

分析

  《算法竞赛入门经典》题解:

  本题是一个典型的状态空间搜索问题,可惜如果直接套用八数码问题的框架会超时。为什么?学完第10章的组合计数部分后会知道:8个1、8个2、8个3的全排列个数为24!/(8!*8!*8!)=9465511770。换句话说,最坏情况下最多要处理这么多结点!

  解决方法很巧妙:本题要求的是中间8个数字相同,即8个1或者8个2或者8个3。因此可以分3次求解。当目标是“中间8个数字都是1”时,2和3就没有区别了(都是“非1”),因此状态总数变成了8个1,16个“非1”的全排列个数,24!/(8!*16!)=735471,在可以接受的范围内了。

  非常好的状态空间分析思路,按这个思路写BFS,虽然较慢但能通过。用迭代加深搜索IDDFS会快一些,最优的方法还是IDA*,其启发式函数可以这样定:当前操作完成后,统计中间8个数字1、2、3数量的最大值x,则至少还需要8-x步操作。IDA*做法其实不需要进行状态空间分析,也就不用分中间8个数字都是1或者2或者3三类情况了。

AC 代码

IDA*

#include <iostream>
using namespace std;#define M 16
const int m = 8, n = 24, c[] = {6, 7, 8, 11, 12, 15, 16, 17}, f[] = {5, 4, 7, 6, 1, 0, 3, 2},idx[][7] = {{0, 2, 6, 11, 15, 20, 22}, {1, 3, 8, 12, 17, 21, 23},{10, 9, 8, 7, 6, 5, 4}, {19, 18, 17, 16, 15, 14, 13},{23, 21, 17, 12, 8, 3, 1}, {22, 20, 15, 11, 6, 2, 0},{13, 14, 15, 16, 17, 18, 19}, {4, 5, 6, 7, 8, 9, 10}};
int v[n]; char a[M+1];int h() {int cnt[] = {0, 0, 0, 0}, mx = 0;for (int j=0; j<m; ++j) mx = max(mx, ++cnt[v[c[j]]]);return m - mx;
}bool IDAStar(int s, int d) {if (s == d) {for (int i=1; i<m; ++i) if (v[c[i]] != v[c[i-1]]) return false;return true;} else for (int i=0; i<m; ++i) if (s == 0 || f[i] != a[s-1]-'A') {int x = v[idx[i][0]];for (int j=1, k=m-1; j<k; ++j) v[idx[i][j-1]] = v[idx[i][j]];v[idx[i][m-2]] = x; a[s] = 'A'+i;if (s+h() < d && IDAStar(s+1, d)) return true;x = v[idx[i][m-2]];for (int j=m-2; j>0; --j) v[idx[i][j]] = v[idx[i][j-1]];v[idx[i][0]] = x;}return false;
}void solve() {for (int i=1; i<n; ++i) cin >> v[i];for (int d=0; d<M; a[++d] = 0) if (IDAStar(0, d)) {cout << (d == 0 ? "No moves needed" : a) << endl << v[c[0]] << endl;break;}
}int main() {while (cin >> v[0] && v[0]) solve();return 0;
}

分3次BFS

#include <iostream>
#include <cstring>
using namespace std;#define M 735471 // C(24,8)
const int m = 8, n = 24, c[] = {6, 7, 8, 11, 12, 15, 16, 17}, f[] = {5, 4, 7, 6, 1, 0, 3, 2},idx[][7] = {{0, 2, 6, 11, 15, 20, 22}, {1, 3, 8, 12, 17, 21, 23},{10, 9, 8, 7, 6, 5, 4}, {19, 18, 17, 16, 15, 14, 13},{23, 21, 17, 12, 8, 3, 1}, {22, 20, 15, 11, 6, 2, 0},{13, 14, 15, 16, 17, 18, 19}, {4, 5, 6, 7, 8, 9, 10}};
int s[M], q[M], p[M], a[M], v[n], g[n], t, b, cc, d; char ans[50], ss[50];bool term() {for (int i=1; i<m; ++i) if (v[c[i]] != v[c[i-1]]) return false;return true;
}bool term2() {for (int i=0; i<m; ++i) if (g[c[i]] != b) return false;return true;
}void insert() {int x = 0;for (int i=0; i<n; ++i) x = x<<1 | (g[i] == b ? 1 : 0);int k = x % M;while (s[k]) {if (s[k] == x) return;k = (k+1) % M;}s[k] = x; q[t++] = k;
}void decode(int x) {for (int i=n-1; i>=0; --i) g[i] = x&1 ? b : 0, x >>= 1;
}void get_path(int f, char c, int d) {if (f) get_path(p[f], char('A'+ a[f]), d-1);ss[d] = c;
}void bfs() {memset(s, t = 0, sizeof(s)); memset(ss, 0, sizeof(ss)); memcpy(g, v, sizeof(v)); ss[0] = 'X'; a[0] = -1; insert();for (int h=0, c=t, dd=1; h<c; ++h) {int k = q[h]; decode(s[k]);for (int i=0; i<m; ++i) if (f[i] != a[h]) {int x = g[idx[i][0]];for (int j=1, k=m-1; j<k; ++j) g[idx[i][j-1]] = g[idx[i][j]];g[idx[i][m-2]] = x;if (term2()) {get_path(h, char('A'+i), dd - 1);if (dd < d || strcmp(ss, ans) < 0) memcpy(ans, ss, sizeof(ss)), cc = b, d = dd;return;}p[t] = h; a[t] = i; insert();x = g[idx[i][m-2]];for (int j=m-2; j>0; --j) g[idx[i][j]] = g[idx[i][j-1]];g[idx[i][0]] = x;}if (h+1 == c) {c = t;if (++dd > d) return;}}
}void solve() {for (int i=1; i<n; ++i) cin >> v[i];if (term()) {cout << "No moves needed" << endl << v[c[0]] << endl;return;}for (b=1, cc=0, d=50; b<4; ++b) bfs();cout << ans << endl << cc << endl;
}int main() {while (cin >> v[0] && v[0]) solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96391.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用pywin32连接autocad 写一个利用遗传算法从选择的闭合图形内进行最优利用率的排版 ai草稿

好的&#xff0c;我们来深入细说遗传算法&#xff08;Genetic Algorithm, GA&#xff09;在钣金自动排版中的应用。遗传算法 (GA) 在钣金排版中的详细解析遗传算法是一种受达尔文生物进化论启发的元启发式优化算法。它不追求一次性找到数学上的绝对最优解&#xff0c;而是通过模…

Go语言io.Copy深度解析:高效数据复制的终极指南

在日常开发中&#xff0c;我们经常需要在不同的数据源之间复制数据。无论是文件操作、网络传输还是进程通信&#xff0c;数据复制都是不可或缺的基础操作。Go语言的标准库提供了一个强大而高效的工具来简化这一过程&#xff1a;io.Copy。 什么是io.Copy&#xff1f; io.Copy是G…

【Vue3】07-利用setup编写vue(2)-setup的语法糖

其它篇章&#xff1a; 1.【Vue3】01-创建Vue3工程 2.【Vue3】02-Vue3工程目录分析 3.【Vue3】03-编写app组件——src 4.【Vue3】04-编写vue实现一个简单效果 5.【Vue3】05-Options API和Composition API的区别 6.【Vue3】06-利用setup编写vue&#xff08;1&#xff09; 7.【Vue…

Firefox自定义备忘

1.设置firefox右键点击标签直接关闭&#xff0c;由于目前没有插件能实现这个功能&#xff0c;只能手动设置了&#xff08;目前已知支持142和之前的版本&#xff09; firefox117右键关闭macWin 117版本应该可以了&#xff0c;大家可试下&#xff0c;配置方法参考之前的帖子&…

跨屏互联KuapingCMS建站系统发布更新 增加数据看板

跨屏互联KuapingCMS建站系统发布更新&#xff0c;增加了文章统计、产品统计、软文统计、流量统计、pv统计、ip统计、os访问者设备统计等等&#xff0c;整个体验会更好&#xff0c;数据显示更加直观&#xff0c;可以清晰看到最近的网站数据&#xff0c;特别是对于老板&#xff0…

WebSocket连接状态监控与自动重连实现

WebSocket连接状态监控与自动重连实现 下面我将实现一个具有连接状态监控和自动重连功能的WebSocket聊天室界面。 设计思路 创建直观的连接状态指示器实现自动重连机制&#xff0c;包括&#xff1a; 指数退避策略&#xff08;重连间隔逐渐增加&#xff09;最大重连次数限制手动…

【Vue2手录05】响应式原理与双向绑定 v-model

一、Vue2响应式原理&#xff08;底层基础&#xff09; Vue2的“响应式”核心是数据变化自动触发视图更新&#xff0c;其实现依赖Object.defineProperty API&#xff0c;但受JavaScript语言机制限制&#xff0c;存在“数组/对象修改盲区”&#xff0c;这是理解后续内容的关键。 …

探索大语言模型(LLM):Ollama快速安装部署及使用(含Linux环境下离线安装)

前言 Ollama 是一个开源的本地化大模型运行平台&#xff0c;支持用户直接在个人计算机上部署、管理和交互大型语言模型&#xff08;LLMs&#xff09;&#xff0c;无需依赖云端服务。而且其混合推理的特性也使得CPU和GPU的算力能够充分被使用&#xff0c;能够在同等配置下跑更大…

渗透测试信息收集详解

我们来详细解析一下渗透测试中信息收集&#xff08;Information Gathering&#xff09;的完整内容、步骤及工具方法。信息收集是整个渗透测试的基石&#xff0c;其深度和广度直接决定了后续测试的成功率&#xff0c;因此有“渗透测试成功与否&#xff0c;90%取决于信息收集”的…

Kafka面试精讲 Day 16:生产者性能优化策略

【Kafka面试精讲 Day 16】生产者性能优化策略 在“Kafka面试精讲”系列的第16天&#xff0c;我们将聚焦于生产者性能优化策略。这是Kafka中极为关键的技术点&#xff0c;也是大厂面试中的高频考点——尤其是在涉及高并发数据写入、日志采集、实时数仓等场景时&#xff0c;面试…

深入解析AI温度参数:控制文本生成的随机性与创造性

引言 在人工智能飞速发展的今天&#xff0c;文本生成模型如GPT系列已经成为内容创作、代码编写、对话系统等领域的核心工具。然而&#xff0c;许多用户在使用这些模型时&#xff0c;可能会发现输出结果有时过于保守和重复&#xff0c;有时又过于天马行空而缺乏连贯性。这背后其…

20250912在荣品RD-RK3588-MID开发板的Android13系统下在接电脑的时候禁止充电

20250912在荣品RD-RK3588-MID开发板的Android13系统下在接电脑的时候禁止充电 2025/9/12 10:21缘起&#xff1a;某人的电脑接荣品RD-RK3588-MID开发板的时候做APK开发板的时候&#xff0c;通过Android Studio连接荣品RD-RK3588-MID开发板。 经常断联/时断时续。投诉了/抱怨了好…

Unity Addressable System 本地服务器功能验证

1.从Package Manger里安装Addressable 注意这里有Addressables和Addressables两个包&#xff0c;前者是核心框架&#xff0c;处理跨平台通用逻辑&#xff0c;比如用 地址&#xff08;Address&#xff09;来异步加载、卸载资源&#xff1b;自动做引用计数&#xff0c;避免资源泄…

碎片化采购是座金矿:数字化正重构电子元器件分销的价值链

在电子元器件的分销江湖里&#xff0c;长期存在着一条隐秘的“鄙视链”&#xff1a;订单金额大、需求稳定的头部客户是众星捧月的“香饽饽”&#xff0c;而需求碎片化、品类繁多的小微企业长尾订单&#xff0c;则常被视作食之无味、弃之可惜的“鸡肋”。行业固有认知告诉我们&a…

Typescript - 通俗易懂的 interface 接口,创建接口 / 基础使用 / 可选属性 / 只读属性 / 任意属性(详细教程)

前言 在面向对象语言中&#xff0c;接口是一个很重要的概念&#xff0c;它是对行为的抽象&#xff0c;而具体如何行动需要由类去实现。 TypeScript 中的接口是一个非常灵活的概念&#xff0c;除了可用于 对类的一部分行为进行抽象 以外&#xff0c;也常用于对「对象的形状&…

【硬件-笔试面试题-92】硬件/电子工程师,笔试面试题(知识点:米勒效应,米勒平台)

题目汇总版--链接&#xff1a; 【硬件-笔试面试题】硬件/电子工程师&#xff0c;笔试面试题汇总版&#xff0c;持续更新学习&#xff0c;加油&#xff01;&#xff01;&#xff01;-CSDN博客 【硬件-笔试面试题-92】硬件/电子工程师&#xff0c;笔试面试题&#xff08;知识点…

C语言深度入门系列:第十一篇 - 动态内存管理与数据结构:程序世界的高效算法大师

C语言深度入门系列&#xff1a;第十一篇 - 动态内存管理与数据结构&#xff1a;程序世界的高效算法大师 本章目标 本章将深入探讨C语言中的动态内存管理和经典数据结构实现&#xff0c;这是从基础编程迈向算法工程师的关键一步。您将掌握内存的精确控制、理解各种数据结构的本质…

Go 语言开发环境安装与 GOPROXY 镜像配置(含依赖管理与版本切换技巧)

在国内搭建 Go 开发环境的最大障碍不是“怎么装”&#xff0c;而是“下不动”。本文是我在多台 Windows / macOS / Linux 机器上踩坑后的整合笔记&#xff1a;用最稳妥的安装方式 合理的镜像配置 一套通吃的依赖/版本管理流程&#xff0c;把速度、稳定性和可维护性一次性解决…

崔传波教授:以科技与人文之光,点亮近视患者的清晰视界‌

崔传波教授&#xff1a;以科技与人文之光&#xff0c;点亮近视患者的清晰视界‌在临沂新益民眼科医院&#xff0c;有这样一位眼科医师——他不仅是近视矫正领域的专家&#xff0c;更是“金视青春之光手术”的研发倡导者。‌崔传波教授‌以其深厚的学术功底、创新的技术理念和以…

如何写过滤条件wrapper的使用

模糊查询 &#xff1a;功能是&#xff1a;查询 WORK_NUM 字段包含 ${workOrder.workNum} 的记录。<if test"workOrder.workNum ! null and workOrder.workNum ! ">and b.WORK_NUM like CONCAT(%,CONCAT(#{workOrder.workNum},%)) </if>一、比较条件方法示…