UVa 10795 - A Different Task 对称, 中间状态, 数位DP 难度: 3
题目
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1736
题意
汉诺塔问题,给定初始状态和最终状态,求最小步数(一定可行)
思路
本来以为是搜索,
如刘书思路。
由于只有三根柱子,假设n-1到i + 1号盘子都已经对齐,对于没有对齐的i号盘子,必要有两根柱子用于转移,一根是现在i所在的柱子,另一根是目的柱子,第三根空闲柱子存放其他无用但是还没对准的小盘子。也即小盘子只能存在空闲柱子上。也即最短路径就是略过已经堆放好的盘子->将无用小盘子堆在空闲柱子上->把最大的没对齐盘子放到应该在的地方这样一个循环。
这样已经能够写出确定性程序,但还存在初始和最终状态都比较复杂的情况。
想到中间状态一定会经过,而忽略掉最后一个还没对齐的最大盘子i的中间状态十分简单,是小盘子[0,...,i-1]在空闲柱子上的简单堆叠,那么可以发现 [0,..., i - 1].终止状态到中间状态的最小步数+ [0,..., i - 1]初始状态到中间状态的最小步数 + 1(移动第i个盘子所需步数) = 总最小步数
而终止状态到中间状态的转换中,移动[0,..., i - 1]到空闲柱子的步数为移动[0, ... , i-2]到新空闲柱子的步数+把[0, ... , i - 2]移回来的步数 + 1(移动i-1),依此类推。(注意有时候不需要移动的情况)
而把[0, ... , i - 2]移回来的步数是2^(i - 2) - 1。
感想
1. 一开始只想到了用搜索暴力做,后来稍微瞄了一眼,也觉得可以用双向bfs来做
2. 之后想到了何为必然出现的状态,也即找到了正确的最短路径,但是还是面临着需要一段段对齐最终状态的问题,代码因此杂乱无章,刘书中提到的将初始和终止状态都转化为清晰简单的中间状态的方法大大减少了实现难度
3. 在实现中一开始不是按照 1 + i-1初始->中间步数 + i-1终止->中间步数来做的,而是按照 i初始->中间步数 + i终止->中间步数,与实际情况不符。
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <tuple>
#include <set>
#include <map>
#include <cassert>
#define LOCAL_DEBUG
using namespace std;
const int MAXN = ;
long long steps[MAXN];
int pegOrg[MAXN];
int pegAim[MAXN]; long long mov(int * pegs, int pos, int desPeg) {
if (pos < ) return ;
if (pegs[pos] == desPeg)return mov(pegs, pos - , desPeg);
return mov(pegs, pos - , - desPeg - pegs[pos]) + steps[pos];
} int main() {
#ifdef LOCAL_DEBUG
freopen("input.txt", "r", stdin);
//freopen("output2.txt", "w", stdout);
#endif // LOCAL_DEBUG
int n;
for (int i = ; i < MAXN; i++) {
steps[i] = 1L << i;
}
for (int ti = ; scanf("%d", &n) == && n; ti++) {
for (int i = ; i < n; i++)scanf("%d", pegOrg + i);
for (int i = ; i < n; i++)scanf("%d", pegAim + i);
long long ans = ;
for (int i = n - ; i >= ; i--) {
if (pegOrg[i] != pegAim[i]) {
ans = mov(pegOrg, i - , - pegAim[i] - pegOrg[i]) + mov(pegAim, i - , - pegAim[i] - pegOrg[i]) + ;
break;
}
}
printf("Case %d: %lld\n", ti, ans);
} return ;
}
UVa 10795 - A Different Task 对称, 中间状态, 数位DP 难度: 3的更多相关文章
- UVa 10795 - A Different Task
题目大意:给出n,表示说有n个大小不同的盘子,然后再给出每个盘子的初始位置和目标位置,要求计算出最少的步数使得每个盘子都移动到它的目标位置. 分析: 首先找最大不在目标柱子上的盘子K,因为如果最大的 ...
- UVA 10795 A Different Task(汉诺塔 递归))
A Different Task The (Three peg) Tower of Hanoi problem is a popular one in computer science. Briefl ...
- UVA 10795 - A Different Task(递归)
A Different Task The (Three peg) Tower of Hanoi problem is a popular one in computer science. Brie ...
- 【汉诺塔问题】UVa 10795 - A Different Task
[经典汉诺塔问题] 汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A.B.C,A座上有64个盘子,盘子大小不等,大的在下,小的在上.有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动 ...
- UVA 10795 A Different Task(模拟)
题目链接:https://vjudge.net/problem/UVA-10795 一道比较有思维含量的一道题: 注意一种分治的思想和“除了柱子x和柱子y之外的那个柱子”编号的问题. 首先在初始局面和 ...
- 数位dp总结 之 从入门到模板
转发自WUST_WenHao巨巨的博客 基础篇 数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数.所谓数位dp,字面意思就是在数位上进行dp咯.数位还算是比较好听 ...
- uva 10712 - Count the Numbers(数位dp)
题目链接:uva 10712 - Count the Numbers 题目大意:给出n,a.b.问说在a到b之间有多少个n. 解题思路:数位dp.dp[i][j][x][y]表示第i位为j的时候.x是 ...
- CF431D Random Task 二分+数位dp
One day, after a difficult lecture a diligent student Sasha saw a graffitied desk in the classroom. ...
- uva 10817(数位dp)
uva 10817(数位dp) 某校有m个教师和n个求职者,需讲授s个课程(1<=s<=8, 1<=m<=20, 1<=n<=100).已知每人的工资c(10000 ...
随机推荐
- IPC 之 ContentProvider 的使用
一.概述 ContentProvider 是 Android 中提供的专门用于不同应用间进行数据共享的方式.和 Messenger 一样,ContentProvider 的底层实现同样也是 Binde ...
- Android 关于虹软人脸识别SDK引擎使用总结
虹软 最近开放了人脸识别的SDK引擎(免费的哦),刚好有Android版的,就体验了一波.下面来说说Android版的SDK使用心得: ArcFace 虹软人脸认知引擎简介 目前开放的版本有人脸比对( ...
- 简单实现Java的RMI——远程方法调用
一.RMI简介: 说到RMI就不得不说RPC了. RPC:(Remote Procedure Call),远程过程调用. RMI(Remote Method Invocation),远程方法调用. R ...
- Codeforces 377A - Maze
A. Maze 题目链接:http://codeforces.com/contest/377/problem/A time limit per test 2 seconds memory limit ...
- spring boot: 支持jsp,支持freemarker
spring boot: 支持jsp,支持freemarker 支持jsp: 加入依赖 <!--jsp--> <dependency> <groupId>org.a ...
- 雷林鹏分享:jQuery EasyUI 树形菜单 - 创建复杂树形网格
jQuery EasyUI 树形菜单 - 创建复杂树形网格 树形网格(TreeGrid)可以展示有限空间上带有多列和复杂数据电子表格.本教程将演示如何将表格数据排列在分割的网格和多行表头中,以便组织共 ...
- 【消息队列】kafka是如何保证高可用的
一.kafka一个最基本的架构认识 由多个broker组成,每个broker就是一个节点:创建一个topic,这个topic可以划分为多个partition,每个partition可以存在于不同的br ...
- 20170822xlVBA ExportCellPhone
Public Sub GetCellPhone() Dim CellPhone As String Dim Arr As Variant Dim Brr As Variant Dim n As Lon ...
- 浅谈微服务架构、容器技术与K8S
关注嘉为科技,获取运维新知 企业应用系统:从单体应用走向微服务架构:从裸金属走向容器. 如果在诸多热门云计算技术诸如容器.微服务.DevOps.OpenStack等之中,找出一个最火的方向,那么可能非 ...
- php二分法查找
//二分查找(数组里查找某个元素) function bin_sch($array, $low, $high, $k) { if ($low <= $high) { $mid = intval( ...