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 ...
随机推荐
- 力扣(LeetCode)202. 快乐数
编写一个算法来判断一个数是不是"快乐数". 一个"快乐数"定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 ...
- DP入门基本问题
个人对简单的dp问题的理解:找是否有重叠问题,明确递推关系,怎么推的(顺序千万不要搞错),找到状态方程,循环时注意边界条件和方程式是否严格成立. 转自:https://www.cnblogs.com/ ...
- 学习笔记9—python数据表的合并(join(), merge()和concat())
merage# pandas提供了一个类似于关系数据库的连接(join)操作的方法<Strong>merage</Strong>,可以根据一个或多个键将不同DataFrame中 ...
- C#读取Excel表格的数据
1.创建工程后,需要下载 EPPlus.dll 添加到工程中,这里有一个下载地址:https://download.csdn.net/download/myunity/10784634 2.下面仅实现 ...
- 第 3 章 镜像 - 021 - Docker 镜像小结
镜像小结 镜像的常用操作子命令: images 显示镜像列表 history 显示镜像构建历史 commit 从容器创建新镜像 build 从 Dockerfile 构建镜像 ...
- c++-pimer-plus-6th-chapter04
Chapter Review 1 a. char actors[30]; b. short betsie[100]; c. float chunk[13]; d. long double dipsea ...
- 20170906xlVBA_GetEMailFromDocument
Public Sub GetDataFromWord() AppSettings 'On Error GoTo ErrHandler Dim StartTime, UsedTime As Varian ...
- php数组的逐行写入文件与读取
<?php /** * * 对数组$arr1=['Apple Orange Banana Strawberry'] 写入文件,并读取 **/ class IoFile { private $pa ...
- 4.1.2 A Funny Game(POJ 2484)
Problem description: n枚硬币排成一个圈,A和B轮流从中取一枚或两枚硬币,不过取两枚时,所取的两枚硬币必须是连续的.硬币取走之后留下空位,相隔空位的硬币视为不连续的.A开始先取,取 ...
- Artem and Array CodeForces - 442C (贪心)
大意: 给定序列$a$, 每次任选$a_i$删除, 得分$min(a_{i-1},a_{i+1})$(无前驱后继时不得分), 求最大得分. 若一个数$x$的两边都比$x$大直接将$x$删除, 最后剩余 ...