洛谷P1242 新汉诺塔(dfs,模拟退火)
最开始的思路是贪心地将盘子从大到小依次从初始位置移动到目标位置。
方法和基本的汉诺塔问题的方法一样,对于盘子 \(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,模拟退火)的更多相关文章
- 洛谷 P1242 新汉诺塔
原题链接 题目描述 设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号.将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A.B.C,这个状态称为初始状态. 现在要求找到一种步数最少的移动方案 ...
- 洛谷P1242 新汉诺塔
传送门啦 首先要将第n个盘子从x到y,那么就要把比n小的盘子全部移到6-x-y,然后将n移到y 仔细想想:6代表的是3根初始柱,3根目标柱. 6-(x+y) 便是我们的中转柱了,因为到这个位置是最优的 ...
- 洛谷P1242 新汉诺塔 【神奇的递归】
题目描述 设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号.将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A.B.C,这个状态称为初始状态. 现在要求找到一种步数最少的移动方案,使得从初 ...
- P1242 新汉诺塔(搜索+模拟退火)
题目链接:传送门 题目大意: 汉诺塔,给定n个盘子(n <= 45),起始状态和结束状态,求最小的步数以及路径. 思路: 考虑用dfs贪心地将剩余最大盘归位. #include<bits/ ...
- BZOJ1019 汉诺塔/洛谷P4285 [SHOI2008]汉诺塔
汉诺塔(BZOJ) P4285 [SHOI2008]汉诺塔 居然是省选题,还是DP!(我的DP菜得要死,碰见就丢分) 冥思苦想了1h+ \(\to\) ?! 就是普通的hanoi NOI or HNO ...
- P1242 新汉诺塔(hanio)
这道题加深了hanio的理解 如果我们要移动第n个盘子.那么就是说,n+1以后(包括n+1)的盘子都已经到位了 #include<iostream> #include<cstdio& ...
- P1242 新汉诺塔
题目描述 设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号.将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A.B.C,这个状态称为初始状态. 现在要求找到一种步数最少的移动方案,使得从初 ...
- 大白_uva10795_新汉诺塔
题意:给出所有盘子的初态和终态,问最少多少步能从初态走到终态,其余规则和老汉诺塔一样. 思路: 若要把当前最大的盘子m从1移动到3,那么首先必须把剩下的所有盘子1~m-1放到2上,然后把m放到3上. ...
- luogu1242 新汉诺塔
就是一步一步把大的往目标地放. #include <iostream> #include <cstdio> using namespace std; int fro[55], ...
随机推荐
- [Python3 练习] 006 汉诺塔2 非递归解法
题目:汉诺塔 II 接上一篇 [Python3 练习] 005 汉诺塔1 递归解法 这次不使用递归 不限定层数 (1) 解决方式 利用"二进制" (2) 具体说明 统一起见 我把左 ...
- 硬核!如何模拟 5w+ 的并发用户?
来自:http://t.cn/ES7KBkW 本文将从负载测试的角度,描述了做一次流畅的5万用户并发测试需要做的事情. 你可以在本文的结尾部分看到讨论的记录. 快速的步骤概要 编写你的脚本 使用JMe ...
- [常用类]Scanner 类
Scanner 类 一个简单的文本扫描器,可以使用正则表达式解析原始类型和字符串. 该代码允许用户从System.in读取一个数字: Scanner sc = new Scanner(System.i ...
- Django - Xadmin (三) 分页、搜索和批量操作
Django - Xadmin (三) 分页.搜索和批量操作 分页和 ShowList 类 因为 list_view 视图函数里面代码太多,太乱,所以将其里面的用于处理表头.处理表单数据的关键代码提取 ...
- 三:GC回收机制
jvm垃圾回收机制: jvm中有个垃圾回收线程,它是低优先级的,当虚拟机空闲或堆内存不足时,它就会去清除不可达对象. GC是如何去判断对象是否能被回收的 早期GC判断对象是否能被回收时用的引用计数法, ...
- 事件对象e的实现原理
转自:https://segmentfault.com/q/1010000007337410?_ea=1313467 事件对象传递原理 1.前置知识回顾 在讲传递原理前,我们先看看普通函数是如何传递参 ...
- Java中的集合详解及代码测试
1:对象数组 (1)数组既可以存储基本数据类型,也可以存储引用类型.它存储引用类型的时候的数组就叫对象数组. 2:集合(Collection) (1)集合的由来 我们学习的是Java -- 面向对象 ...
- Spark2.0 Java实现将Hive运算结果保存到数据库
package com.gm.hive.SparkHive; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; ...
- 学Python的第五天
最近忙着学MySQL,但是小编也不会放弃学Python!!! 因为热爱所以学习~ 好了各位,进入正题,由于时间问题今天学的不是很多.... #!/usr/bin/env python # -*- co ...
- 脚本_统计 Linux 进程相关数量信息
#!bin/bash#作者:liusingbon#功能:统计 Linux 进程相关数量信息,running(运行的进程),sleeping(睡眠中的进程),stoped(停止的进程),zombie(僵 ...