hdu 2770 Easy Climb
来源:互联网 发布:阿里云香港服务器官网 编辑:程序博客网 时间:2024/06/03 21:14
又是一道写了老久的题目。。。。
题意是有n个台阶,要求通过调整使台阶之间相邻高度差均小于等于一个正整数D,调整一个台阶所花的代价为这个台阶改变后和改变前的高度差的绝对值。求最小代价的值。(第一个台阶和最后的台阶高度不可变,所以当无法实现要求时输出impossible)。
嘛,这种最优问题一般就是DP。
状态方程也是好想,dp [ i ] [ j ] 代表第 i 个台阶取第 j 种值所能得到的最小值。那么dp [ i ] [ j ] = min ( dp [ i-1 ] [ k ] ) { abs ( Val [ j ] - Val [ k ] ) < D } + High [ i ] - Val [ j ] ;其中Val数组存的是状态点,High数组存的是原来输入的台阶高度。
然后重点就是状态点的选取了,第一次想的是用每个点的初始值High[ i ]和其扩展值High[ i ] + D 和 High[ i ] - D,因为根据当前题目的要求,最优值肯定都是出现在这种界限值上的。然后交一发WA~
第二次找到了错误的数据,类似于 2 0 0 0 0 12 这种台阶高度分布,如果高度差合适是可以实现要求的。但是用第一次的方法的话,中间状态点就会出现断层,造成输出变成无法实现。那就有必要把扩展值的范围增大,就是High [ i ] + D * j ( -Num <= j <= Num )了。然后提交~TLE
恩,扩展了之后忘记考虑时间复杂度了(╯‵□′)╯︵┻━┻
第三次改了改,根据它扫描的特性,模拟了栈存最小值。因为处理min ( dp [ i-1 ] [ k ] )的时候,k所占据的范围是从左向右移动的,那么我们只要把范围内的数据存在于栈内,一旦当前从右端进入的值小于栈顶,那就一直下沉至比其更小的值处,相当于是——如果当前值并不比之前出现的值更优,那就选择直接存入,否则将该值之前的所有次值覆盖。这个栈的特性就是越底层其值越优,但由于不一定都是归属于当前范围,所以我们需要设定一个Best值来定位范围内的最优值(从零开始一直往上搜索即可)。那么时间复杂度的问题也就解决了。AC~
#include <stdio.h>#include <algorithm>using namespace std;typedef __int64 LL;const int MAXM = 110;const LL INF = (LL)1<<50;int All;int Num;int Left,Right;LL Limit;LL High[MAXM];LL List[MAXM*MAXM<<1];LL A[MAXM*MAXM<<1],B[MAXM*MAXM<<1];int End;int Top;int Best;LL Stack[MAXM*MAXM<<1]; void Read_Case(){All=1;List[0]=0;scanf("%d %I64d",&Num,&Limit);for(int i=1;i<=Num;i++){scanf("%I64d",High+i);for(int j=Num;j>=-Num;j--){List[All++]=High[i]+Limit*j;if(List[All-1]<=0)break;}}sort(List,List+All);int now=1;for(int i=1;i<All;i++){if(List[i]!=List[i-1])List[now++]=List[i];}All=now;List[All]=INF;}void Stack_In(int Val,LL *Table){while(List[End]-Val<=Limit){while(Top>Best&&Table[End]<Table[Stack[Top-1]]){Top--;}Stack[Top++]=End++;}while(Best<Top&&Val-List[Stack[Best]]>Limit){Best++;}}void Deal(){LL *Now=A,*Ago=B,*G;for(int i=0;i<All;i++){if(High[1]==List[i])Ago[i]=0;else Ago[i]=INF;}for(int i=2;i<=Num;i++){End=Top=Best=0;for(int j=0;j<All;j++){Stack_In(List[j],Ago);Now[j]=Ago[Stack[Best]]+abs(High[i]-List[j]);}G=Now;Now=Ago;Ago=G;}LL ans;for(int i=0;i<All;i++){if(List[i]==High[Num])ans=Ago[i];}if(ans>=INF)puts("impossible");else printf("%I64d\n",ans);}int main(){int T;scanf("%d",&T);while(T--){Read_Case();Deal();}}
真是错成马啊~
- HDU 2770 Easy Climb
- HDU-2770-Easy Climb
- hdu 2770 Easy Climb
- Hdu-2770 Easy Climb(DP优化)
- 12170 - Easy Climb
- uva12170 Easy Climb
- Easy Climb UVA
- Easy Climb UVA
- UVA 12170 Easy Climb(dp+ 单调队列)
- Easy Climb - UVa 12170 dp+优先队列
- UVa #12170 Easy Climb (例题9-25)
- 12170 - Easy Climb(DP+单调队列)
- UVALive 4290 Easy Climb(dp + 精简状态 + 优先队列)
- UVA 12170 Easy Climb(dp+单调队列优化)
- UVA - 12170 Easy Climb 轻松爬山 单调队列优化DP
- 【暑假】[深入动态规划]UVa 12170 Easy Climb
- UVA 12170 Easy Climb 【单调队列优化DP+状态简化】
- YT14-HDU-The snail climb well
- JDBC连接数据库
- 30款css3实现的鼠标经过图片显示描述特效
- [历年IT笔试题]2014京东校园招聘-软件开发笔试题
- 使用get_argument获取url query参数
- 为何get_argument不区分POST与GET?
- hdu 2770 Easy Climb
- STL关联容器
- get_argument返回unicode数据类型的问题
- Cocos2d-x虚拟摇杆控制精灵上下左右运动----之游戏开发《赵云要格斗》(1) cocos2dx 3.3移植版
- 为什么要阅读Tornado的源码?
- 自定义View(1)---Topbar
- 06-0. 混合类型数据格式化输入(5)
- Commando War
- while(cin>>s)退出问题