UVALive 3983 Robotruck (单调队列)
来源:互联网 发布:易语言断网瞬移源码 编辑:程序博客网 时间:2024/06/01 21:48
题目链接~~>
做题感悟:这是接触的单调队列的第一题,终于把它弄懂了,结合白书以及网上的各种资料。
解题思路: 单调队列DP
这题的重点就在变换动态转移方程上,首先设 dp[ i ] 为处理到第 i 个垃圾所用的最小距离,那么很容易想到动态转移方程:dp[ i ] = min { dp[ j ] + d( j + 1 ) + d( j + 1 , i ) + d( i ) } 且 w( j + 1 , i ) <= W , 解释一下:d( i ) 为 i 点到原点的距离(指哈密顿距离),d( j + 1 ,i) 代表 从j + 1 到 i 的距离和。w(j + 1 , i ) 为从 j + 1 到 i 的重量和。W 为最大重量。
好了,接下来就是怎样去转化动态方程了:我们用前缀和的思想分别记录前缀距离和前缀重量,分别用数组 sumd[ i ] ,sumw[ i ] ,d[ i ] 为点i 到原点的距离,这样方程就可以变为:
dp[ i ] = min { dp[ j ] + d[ j +1 ] + sumd[ i ] - sumd[ j + 1] + d[ i ] } 且 sumw[ i ] - sum[ j ] <= W ;
进一步转变 ===>
dp[ i ] = min{dp[ j ] + d[ j + 1 ] - sumd[ j + 1 ] } + sumd[ i ] + d[ i ] ; 变成这样后你会发现前面的各个数只与本身相关,可以把他们放入一个队列中,只要维护队列的最小值(在重量满足的前提下),那么计算dp[ i ]的时间就变成O( 1 ) 的了。切记:队尾的结尾的元素为 end - 1
具体见代码:
#include<iostream>#include<sstream>#include<map>#include<cmath>#include<fstream>#include<queue>#include<vector>#include<sstream>#include<cstring>#include<cstdio>#include<stack>#include<bitset>#include<ctime>#include<string>#include<cctype>#include<iomanip>#include<algorithm>using namespace std ;#define INT long long int#define L(x) (x * 2)#define R(x) (x * 2 + 1)const int INF = 0x3f3f3f3f ;const double esp = 0.0000000001 ;const double PI = acos(-1.0) ;const int mod = 1000000007 ;const int MY = (1<<5) + 5 ;const int MX = 100010 + 5 ;int n ,W ;int sumw[MX] ,d[MX] ,dp[MX] ,deq[MX] ,sumd[MX] ;int Cavalue(int j){ return dp[j] + d[j+1] - sumd[j+1] ;}void input(){ int x ,y ,w ; scanf("%d%d" ,&W ,&n) ; sumw[0] = sumd[0] = d[0] = 0 ; int x1 = 0 ,y1 = 0 ; for(int i = 1 ;i <= n ; ++i) { scanf("%d%d%d" ,&x ,&y ,&w) ; sumw[i] = sumw[i-1] + w ; // 重量的前缀和 d[i] = abs(x) + abs(y) ; // 到原点的距离 sumd[i] = sumd[i-1] + abs(x-x1) + abs(y-y1) ; // 距离前缀和 x1 = x ; y1 = y ; }}void DP(){ memset(deq ,0 ,sizeof(deq)) ; int front = 0 ,end = 0 ; // deq 双端队列的头和尾 for(int i = 1 ;i <= n ; ++i) { while(front < end && Cavalue(deq[end-1]) >= Cavalue(i-1)) // 因为 end 没减一错了好久 end-- ; deq[end++] = i-1 ; while(front < end && sumw[i] - sumw[deq[front]] > W) front++ ; dp[i] = Cavalue(deq[front]) + d[i] + sumd[i] ; }}int main(){ int Tx ; scanf("%d" ,&Tx) ; while(Tx--) { input() ; DP() ; cout<<dp[n]<<endl ; if(Tx) cout<<endl ; } return 0 ;}
- UVALive 3983 Robotruck (单调队列)
- UVALive - 3983 - Robotruck (DP+单调队列)
- LA 3983 Robotruck / 单调队列
- LA 3983 - Robotruck 单调队列优化DP
- UVALive 3983 Robotruck
- UVALive - 3983 Robotruck DP
- UVALive 3983 Robotruck
- uva 1169 - Robotruck (单调队列优化dp)
- LA3983 Robotruck (单调队列优化DP)
- uva 1169 - Robotruck(dp+单调队列)
- UVA 1169 Robotruck 单调队列优化 DP
- LA3983-Robotruck(dp + 单调队列)
- uvalive 4726(单调队列)
- 【暑假】[深入动态规划]UVAlive 3983 Robotruck
- UVAlive - 3983—— Robotruck
- UVA 1169 Robotruck(dp+单调队列滑动窗口)
- UVALive 4726Average 单调队列+斜率优化
- *UVA 1169Robotruck ACM解题报告(dp单调队列优化)
- C++中内联函数与宏
- 记录9--双系统删除grup
- 程矢Axure夜话:中继器系列视频教程之中继器原型设计二十一条军规
- Python深入06 Python的内存管理
- spark sql
- UVALive 3983 Robotruck (单调队列)
- DB9定义
- 黑马程序员——Java基础——IO流笔记(自定义BufferedInputStream流---装饰器模式)
- 懒加载TreeViewer
- [WiFi教程] 轻松教你支持ZTE中兴客户端
- 程矢Axure夜话:中继器系列视频教程之中继器网格实现
- 移动设备的网络通信
- 谈谈软件开发那些事 笔记3
- 最好的编程语言(如何不再担忧,爱上代码)