洛谷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. 分布式 vs 集群 主从 vs 集群

      理解 分布式 一个业务拆分成多个子业务,部署在不同的服务器上 集群 同一个业务部署在多个服务器上   更新 主从 服务器之间更新是异步的,从服务器可能和主服务器不一致 集群 更新是同步的,数据节点 ...

  2. Haystack Python全文检索框架

    Haystack 1.什么是Haystack Haystack是django的开源全文搜索框架(全文检索不同于特定字段的模糊查询,使用全文检索的效率更高 ),该框架支持Solr,Elasticsear ...

  3. Vue+axios+Node+express实现文件上传(用户头像上传)

    Vue 页面的代码 <label for='my_file' class="theme-color"> <mu-icon left value="bac ...

  4. Java缓存Ehcache-Ehcache的Cache在SSM框架中的配置

    需要在Spring配置文件中配置: <!-- 配置缓存管理器工厂 --> <bean id="cacheManager" class="org.spri ...

  5. express通过生成器

    express通过生成器 [ 脚手架 ] 1. 作用:可以帮助快速构建一个express项目 2. 脚手架的安装 全局安装 [可以使用npm cnpm] $ cnpm i express-genera ...

  6. iis8.5部署net项目

    服务器上运行提示: iis版本: 使用命令行运行cmd(管理员模式) 输入: %windir%\system32\inetsrv\appcmd unlock config -section:syste ...

  7. nodejs 模板引擎

    自制替换模板 template.js var fs = require('fs') var http = require('http') var server = http.createServer( ...

  8. 一、Vs2019扩展多了 导航到反编译的源码中运行

    一.导航到反编译的源码中运行

  9. CentOS 7 FTP的安装与配置

    CentOS7 FTP安装与配置 1.FTP的安装 #安装yum install -y vsftpd #设置开机启动systemctl enable vsftpd.service #启动systemc ...

  10. python常用函数 Y

    yield有点像return,但他会在下一次执行的时候从上次结束点继续执行,带有 yield 的函数在 Python 中被称之为 generator(生成器),生成器无法通过索引获取数据,同时也承诺使 ...