[jzoj]1229. Hanoi(DP决策最优性优化)
2017-08-15 19:50
190 查看
Description
Mpq 小时候只玩过俄罗斯方块这个经典的小游戏,当时他还不知道Hanoi 究竟是
什么东西。话说当Mpq 第一次认识Hanoi 是在初三那年的联赛。由于Mpq 之前并不知
道Hanoi 是什么东西,所以那一年他做完前三题之后很郁闷地坐了1 个半小时。。。
好了,现在Mpq 成长了,他已经解决当年联赛那道Hanoi 了,在前几个月,他又
发现一道关于Hanoi 的题目了,很幸运的是这个题目他知道怎么做了。。。然后为了让大
家体验一下Mpq 初三联赛那种无奈的感觉,所以,这道题就神奇地出现在你们眼前。
Task:赶快AC 这道题目,然后你就可以狂鄙视,甚至是无视Mpq 的存在了!!!
哎,吹着吹着发现我还没把题目写下来。。。。
现在给你M 根柱子,初始的时候有N 个大小不一样的盘插在第一根柱子上面。同
样地,规格大的盘子不能放在规格比它小的盘子上面。问最少需要多少次的移动才能将
这N 个盘从第一根柱子移动到最后一根柱子上面?
Input
输入文件的第一行有两个整数n,m(1≤n≤100000,3≤m≤10),分别表示有n 个盘子和m
根柱子。
Output
输出文件只有一行,一个整数,表示最少的移动次数。保证这个移动次数不会超过
2^63-1。
Sample Input
4 3
Sample Output
15
Data Constraint
数据约定:
对于30%的数据,M=3
对于80%的数据,1≤N≤100,3≤M≤10
对于100%的数据,1≤N≤100000,6≤M≤10
我们设f[i][j]表示把j个盘子从第一根柱子移到第i根柱子的最少方案数.
首先,一个很显然的结论:
柱子相对多,盘子固定,肯定方案相对优.
相对是因为如果把当柱子已经大于盘子,那么再增加柱子都不会更优.
发现,如果每次多增一个柱子,盘子相同,那么方案数更新的次数难以计算.
那我们考虑柱子相同,如果每次多增加一个盘子,方案数应该怎么算?
显然,就是f[i][j]=Min{f[i][k]+f[i−1][j−k]} .
但是k是枚举的,这样更新状态是O(n)的,总时间复杂度O(n2∗m)
我们考虑最优状态应该是怎样的?
记录一个g[i][j]表示当有i根柱子,j个盘子时的最优决策,即是先把前g[i][j]个盘子从第一根柱子移到其他柱子去,然后再把剩下的j−g[i][j]个盘子移到第i根柱子去.
那么假设我现在由f[i][j]−>f[i][j+1],如何转移呢?
很显然就是利用g[i][j],因为当前多了一个盘子,我不可能先移前g[i][j]−1个盘子,否则g[i][j]不可能是最优的.
同理,我也不可能移前g[i][j]+2个盘子,否则g[i][j]也不是最优的,这里可以感性+理性的理解,无需证明.
那么转移就分两种,处理一下边界就好了.
Mpq 小时候只玩过俄罗斯方块这个经典的小游戏,当时他还不知道Hanoi 究竟是
什么东西。话说当Mpq 第一次认识Hanoi 是在初三那年的联赛。由于Mpq 之前并不知
道Hanoi 是什么东西,所以那一年他做完前三题之后很郁闷地坐了1 个半小时。。。
好了,现在Mpq 成长了,他已经解决当年联赛那道Hanoi 了,在前几个月,他又
发现一道关于Hanoi 的题目了,很幸运的是这个题目他知道怎么做了。。。然后为了让大
家体验一下Mpq 初三联赛那种无奈的感觉,所以,这道题就神奇地出现在你们眼前。
Task:赶快AC 这道题目,然后你就可以狂鄙视,甚至是无视Mpq 的存在了!!!
哎,吹着吹着发现我还没把题目写下来。。。。
现在给你M 根柱子,初始的时候有N 个大小不一样的盘插在第一根柱子上面。同
样地,规格大的盘子不能放在规格比它小的盘子上面。问最少需要多少次的移动才能将
这N 个盘从第一根柱子移动到最后一根柱子上面?
Input
输入文件的第一行有两个整数n,m(1≤n≤100000,3≤m≤10),分别表示有n 个盘子和m
根柱子。
Output
输出文件只有一行,一个整数,表示最少的移动次数。保证这个移动次数不会超过
2^63-1。
Sample Input
4 3
Sample Output
15
Data Constraint
数据约定:
对于30%的数据,M=3
对于80%的数据,1≤N≤100,3≤M≤10
对于100%的数据,1≤N≤100000,6≤M≤10
Solution
这是一道很牛逼的DP.我们设f[i][j]表示把j个盘子从第一根柱子移到第i根柱子的最少方案数.
首先,一个很显然的结论:
柱子相对多,盘子固定,肯定方案相对优.
相对是因为如果把当柱子已经大于盘子,那么再增加柱子都不会更优.
发现,如果每次多增一个柱子,盘子相同,那么方案数更新的次数难以计算.
那我们考虑柱子相同,如果每次多增加一个盘子,方案数应该怎么算?
显然,就是f[i][j]=Min{f[i][k]+f[i−1][j−k]} .
但是k是枚举的,这样更新状态是O(n)的,总时间复杂度O(n2∗m)
我们考虑最优状态应该是怎样的?
记录一个g[i][j]表示当有i根柱子,j个盘子时的最优决策,即是先把前g[i][j]个盘子从第一根柱子移到其他柱子去,然后再把剩下的j−g[i][j]个盘子移到第i根柱子去.
那么假设我现在由f[i][j]−>f[i][j+1],如何转移呢?
很显然就是利用g[i][j],因为当前多了一个盘子,我不可能先移前g[i][j]−1个盘子,否则g[i][j]不可能是最优的.
同理,我也不可能移前g[i][j]+2个盘子,否则g[i][j]也不是最优的,这里可以感性+理性的理解,无需证明.
那么转移就分两种,处理一下边界就好了.
#include <iostream> #include <cstring> #include <cstdio> #define maxn 100001 #define maxm 61 #define LL long long #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; LL n,m,i,j,k; LL f[maxm][maxn],g[maxm][maxn]; int main(){ scanf("%lld%lld",&n,&m); memset(f,30,sizeof(f)); f[2][0]=0; f[2][1]=1; f[3][0]=0; f[3][1]=1; //f[3][2]=3; f[3][3]=7; f[3][4]=15; fo(i,3,m) { f[i][1]=1; g[i][1]=0; fo(j,2,n){ k=g[i][j-1]; if ((f[i][k]<<1)+f[i-1][j-k]<(f[i][k+1]<<1)+f[i-1][j-k-1]) { f[i][j]=(f[i][k]<<1)+f[i-1][j-k]; g[i][j]=k; } else { f[i][j]=(f[i][k+1]<<1)+f[i-1][j-k-1]; g[i][j]=k+1; } } } printf("%lld",f[m] ); }
相关文章推荐
- Lightning Conductor 洛谷P3515 决策单调性优化DP
- [jzoj]4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰(线段树优化DP)
- [BZOJ1563][NOI2009]诗人小G(决策单调性优化DP)
- [jzoj]1262. 为奶牛熄灯(迭代加深搜索+一堆优化vs记忆化vs状压DP)
- 【DP+斜率优化】JZOJ3574 harbingers
- bzoj2369 && 2687 -- 决策单调性优化DP
- bzoj1563: [NOI2009]诗人小G【决策单调性优化dp】
- Bzoj:[Poi2011]Lightning Conductor:决策单调性优化DP详解
- [BZOJ1010][HNOI2008]玩具装箱(决策单调性/斜率优化DP)
- 1D/1D优化dp之利用决策点的凸性优化
- DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)
- HDU3507 BZOJ1010 DP决策单调优化 pascal
- JZOJ1229. Hanoi(2017.8B组)
- 【JZOJ 3432】服务器 斜率优化DP常见问题&详细解答
- BZOJ.1010.[HNOI2008]玩具装箱toy(DP 斜率优化/单调队列 决策单调性)
- Codeforces868F Yet Another Minimization Problem -- 决策单调性优化DP
- 1010: [HNOI2008]玩具装箱toy DP+斜率优化+决策单调性
- [NOI2009]诗人小G(决策单调性优化dp)
- JZOJ5347【NOIP2017提高A组模拟9.5】遥远的金字塔 斜率优化 DP
- poj 1180 Batch Scheduling(斜率优化dp或决策单调)