洛谷P1242 新汉诺塔

最开始的思路是贪心地将盘子从大到小依次从初始位置移动到目标位置。

方法和基本的汉诺塔问题的方法一样,对于盘子 \(i\) ,将盘子 \(1\to i-1\) 放置到中间柱子上,即 \(6 - from - to\) 号柱子。基本递归实现。

但是贪心的优先将大盘移动到指定位置存在一些特殊情况处理错误。

例如如下数据,最优的方案并不是把大盘一步移到位,而是先移到了一根空柱上。

3
1 3
0
2 2 1
2 2 1
0
1 3 move 3 from A to B
move 1 from C to B
move 2 from C to A
move 1 from B to A
move 3 from B to C
5

这里使用模拟退火对算法(玄学)进行改进。

在移动一些盘子的时候不直接移到目标柱子上,这个不直接移到目标柱子上的操作是有一定概率的,这个概率随时间的增加而缩小。

因为模拟退火为随机算法,所以我们跑几百次取最优为最终答案。

#include<stdio.h>
#include<iostream>
#include<string>
#include<cstdlib>
#include<ctime> using namespace std; const int maxn = 50;
const int _time = 205;
const int inf = 0x3f3f3f3f;
int from[maxn], to[maxn], _from[maxn], _to[maxn];
int n, m, x, cnt, _cnt;
string ans, _ans, M[5] = {"0", "A", "B", "C"}; void dfs(int x, int a, int b)
{
if(a == b) return;
for(int i = x - 1; i >= 1; i--) dfs(i, from[i], 6 - a - b);
from[x] = b;
cnt++;
ans += "move ";
if(x>=10) ans += char(x / 10 + 48), ans += char(x % 10 + 48);
else ans += char(x + 48);
ans += " from "; ans += M[a]; ans += " to "; ans += M[b]; ans += "|";
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= 3; i++){
scanf("%d", &m);
for(int j = 1; j <= m; j++){
scanf("%d", &x); _from[x] = i;
}
}
for(int i = 1; i <= 3; i++){
scanf("%d", &m);
for(int j = 1; j <= m; j++){
scanf("%d", &x); _to[x] = i;
}
}
srand(time(0));
_cnt = inf;
for(int cas = 1; cas <= _time; cas++){
ans = ""; cnt = 0;
for(int i = 1; i <= n; i++) from[i] = _from[i], to[i] = _to[i];
for(int i = n; i >= 1; i--){
/***m模拟退火***/
if(rand() % (n - i + 2) == 0) dfs(i, from[i], 6 - from[i] - to[i]);
else dfs(i, from[i], to[i]);
}
for(int i = n; i >= 1; i--){
dfs(i, from[i], to[i]);
}
if(cnt < _cnt){
_cnt = cnt; _ans = ans;
}
}
for(int i = 0; i < _ans.size(); i++){
if(_ans[i] == '|') puts("");
else printf("%c", _ans[i]);
}
printf("%d\n", _cnt);
return 0;
}

洛谷P1242 新汉诺塔(dfs,模拟退火)的更多相关文章

  1. 洛谷 P1242 新汉诺塔

    原题链接 题目描述 设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号.将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A.B.C,这个状态称为初始状态. 现在要求找到一种步数最少的移动方案 ...

  2. 洛谷P1242 新汉诺塔

    传送门啦 首先要将第n个盘子从x到y,那么就要把比n小的盘子全部移到6-x-y,然后将n移到y 仔细想想:6代表的是3根初始柱,3根目标柱. 6-(x+y) 便是我们的中转柱了,因为到这个位置是最优的 ...

  3. 洛谷P1242 新汉诺塔 【神奇的递归】

    题目描述 设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号.将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A.B.C,这个状态称为初始状态. 现在要求找到一种步数最少的移动方案,使得从初 ...

  4. P1242 新汉诺塔(搜索+模拟退火)

    题目链接:传送门 题目大意: 汉诺塔,给定n个盘子(n <= 45),起始状态和结束状态,求最小的步数以及路径. 思路: 考虑用dfs贪心地将剩余最大盘归位. #include<bits/ ...

  5. BZOJ1019 汉诺塔/洛谷P4285 [SHOI2008]汉诺塔

    汉诺塔(BZOJ) P4285 [SHOI2008]汉诺塔 居然是省选题,还是DP!(我的DP菜得要死,碰见就丢分) 冥思苦想了1h+ \(\to\) ?! 就是普通的hanoi NOI or HNO ...

  6. P1242 新汉诺塔(hanio)

    这道题加深了hanio的理解 如果我们要移动第n个盘子.那么就是说,n+1以后(包括n+1)的盘子都已经到位了 #include<iostream> #include<cstdio& ...

  7. P1242 新汉诺塔

    题目描述 设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号.将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A.B.C,这个状态称为初始状态. 现在要求找到一种步数最少的移动方案,使得从初 ...

  8. 大白_uva10795_新汉诺塔

    题意:给出所有盘子的初态和终态,问最少多少步能从初态走到终态,其余规则和老汉诺塔一样. 思路: 若要把当前最大的盘子m从1移动到3,那么首先必须把剩下的所有盘子1~m-1放到2上,然后把m放到3上. ...

  9. luogu1242 新汉诺塔

    就是一步一步把大的往目标地放. #include <iostream> #include <cstdio> using namespace std; int fro[55], ...

随机推荐

  1. Java 中的 T,E,K,V, 别傻傻分不清楚!

    作者:glmapper https://juejin.im/post/5d5789d26fb9a06ad0056bd9 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛 ...

  2. 使用MySQL Workbench进行数据库设计——MySQL Workbench使用方法总结

    本文出自[我是干勾鱼的博客] 转自:https://blog.csdn.net/dongdong9223/article/details/48318877 1 创建Model(设计ER图) 使用wor ...

  3. ML5238电池管理芯片笔记

          根据公司需要开发了以ML5238电池管理芯片+STM8S为核心的电池管理系统.由于前期对BMS系统还是了解甚少,开发起来也遇到了不少困难.再开发管理系统的同时,我也开发了管理系统的上位机, ...

  4. dp(电梯与楼梯)

    http://codeforces.com/problemset/problem/1249/E E. By Elevator or Stairs? time limit per test 2 seco ...

  5. k3 cloud套打模板中绑定加税合价字段的时候数据都为空,不绑定的时候显示正常

    检查bos中加税合计字段,是不是关联币别绑定错误

  6. 用jquery制作的简单轮播图

    我也是进入H5前端的小菜鸟一枚,最近才进入jquery的学习,所以打算对自己的学习进行记录. 今天分享的是一个简单的轮播图,这个轮播图的特效很简单,能够进行图片的轮播以及点击相应图片,图片能够跳转到相 ...

  7. Java REST Client API

    https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high-supported-apis.htm ...

  8. 【容器化】容器技术实践.pdf_视频学习笔记

    容器运行时 docker rkt gvisor containerd 容器编排系统:kubernetes (简称k8s)

  9. CSS3 ::before和::after伪元素的实际应用

    实例 1.清除浮动 通常我们清除清除浮动的方式就是在浮动元素后面添加一个空的Div标签,然后在设置它的清除浮动要是,使用after伪元素,我们就不需要添加无意义的div标签在html中了,下面的例子就 ...

  10. wannafly25 E 01串

    链接 wannafly25 E 01串 给出一个\(01\)串,有两种操作,操作一是将某一个位置的数字修改,操作二是询问某一个区间,将这个区间看做\(1\)个二进制数,可以随意加减\(2\)的幂次,问 ...