【暑假】[深入动态规划]UVAlive 3983 Robotruck
UVAlive 3983 Robotruck
题目:
Time Limit: 3000MS | Memory Limit: Unknown | 64bit IO Format: %lld & %llu |
Description
Background
This problem is about a robotic truck that distributes mail packages to several locations in a factory. The robot sits at the end of a conveyer at the mail office and waits for packages to be loaded into its cargo area. The robot has a maximum load capacity, which means that it may have to perform several round trips to complete its task. Provided that the maximum capacity is not exceeded, the robot can stop the conveyer at any time and start a round trip distributing the already collected packages. The packages must be delivered in the incoming order.
The distance of a round trip is computed in a grid by measuring the number of robot moves from the mail office, at location (0,0), to the location of delivery of the first package, the number of moves between package delivery locations, until the last package, and then the number of moves from the last location back to the mail office. The robot moves a cell at a time either horizontally or vertically in the factory plant grid. For example, consider four packages, to be delivered at the locations (1,2), (1,0), (3,1), and (3,1). By dividing these packages into two round trips of two packages each, the number of moves in the first trip is 3+2+1=6, and 4+0+4=8 in the second trip. Notice that the two last packages are delivered at the same location and thus the number of moves between them is 0.
Problem
Given a sequence of packages, compute the minimum distance the robot must travel to deliver all packages.
Input
Input consists of multiple test cases the first line of the input contains the number of test cases. There is a blank line before each dataset. The input for each dataset consists of a line containing one positive integer C, not greater then 100, indicating the maximum capacity of the robot, a line containing one positive integer N, not greater than 100,000, which is the number of packages to be loaded from the conveyer. Next, there are N lines containing, for each package, two non-negative integers to indicate its delivery location in the grid, and a positive integer to indicate its weight. The weight of the packages is always smaller than the robot�s maximum load capacity. The order of the input is the order of appearance in the conveyer.
Output
One line containing one integer representing the minimum number of moves the robot must travel to deliver all the packages. Print a blank line between datasets.
Sample Input
1
10
4
1 2 3
1 0 3
3 1 4
3 1 4
Sample Output
14
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
思路:
设d[i]为将前i个垃圾收完并放进垃圾桶的最小距离。同时定义total_dist[i]为从0点依次走过前i个垃圾到i的曼哈顿距离和,定义dist2origin[i]为i到0点的曼哈顿距离。
转移方程:
d[i]=min{d[j]-total_dist(j+1)+dist2origin(j+1) // j 满足w(j+1,i)<=c } +total_dist[i]+dist2origin[i] //代表一次将j+1..i的垃圾收回放到0点
单调队列优化:
设func(j)=d[j]-total_dist(j+1)+dist2origin(j+1) 则转移方程为:d[i]=min{func(j) // j 满足w(j+1,i)<=c } + ...
用单调队列维护一个满足w(q[front]+1,i)<=c的滑动窗口,单调队列中的值按照func的递增序排列。每次考虑一个新的i 都要适当移动窗口,使得满足单调队列的性质。维护的单调队列可以在O(1)的时间内返回min{func(j) // j 满足w(j+1,i)<=c}
具体操作如下:
int q[maxn]; //单调队列
front=rear=;
for(int i=;i<=n;i++) {
while(front<=rear && total_w[i]-total_w[q[front]]>c) front++; //维护队列中w(j+1,i)<=c
d[i]=func(q[front]) + total_dist[i] + dist2origin[i]; //func(q[front])是队列中的最小值
while(front<=rear && func(i)<=func(q[rear])) rear--; //维护单调队列中的单调递增序
q[++rear]=i;
}
完整代码:
#include<iostream>
#include<algorithm>
using namespace std; const int maxn = + ; int x[maxn],y[maxn];
int total_dist[maxn],dist2origin[maxn],total_w[maxn];
int d[maxn]; inline int func(int j) {
return d[j]-total_dist[j+]+dist2origin[j+];
} int main() {
int T,n,c,w,front,rear;
cin>>T;
while(T--) {
cin>>c>>n;
total_w[]=total_dist[]=x[]=y[]=;
for(int i=;i<=n;i++) {
cin>>x[i]>>y[i]>>w;
total_w[i]=total_w[i-]+w;
total_dist[i]=total_dist[i-]+abs(x[i]-x[i-])+abs(y[i]-y[i-]);
dist2origin[i]=abs(x[i])+abs(y[i]);
} int q[maxn];
front=rear=;
for(int i=;i<=n;i++) {
while(front<=rear && total_w[i]-total_w[q[front]]>c) front++;
d[i]=func(q[front]) + total_dist[i] + dist2origin[i];
while(front<=rear && func(i)<=func(q[rear])) rear--;
q[++rear]=i;
} cout<<d[n]<<endl;
if(T) cout<<endl;
}
}
【暑假】[深入动态规划]UVAlive 3983 Robotruck的更多相关文章
- [UVALive 3983] Robotruck
图片加载可能有点慢,请跳过题面先看题解,谢谢 设状态 \(f[i][j]\) 为,当前垃圾序号为 \(i\) ,当前承重为 \(j\) 的最小路程,好的这道题做完了 O(NC) G烂 $ $ 我们这样 ...
- UVALive 3983 Robotruck (单调队列,dp)
如果状态定义为序号和重量的话,决策就是下一个垃圾捡或者不减,但是状态数太多了. 如果只定义序号作为状态的话,决策就变成从前面的某个j一直捡到i才送回垃圾. 这就变成了一个区间选最小值的问题,用单调队列 ...
- UVaLive 3983 Robotruck (DP + 单调队列)
题意:有n个垃圾,第i个垃圾坐标为(xi,yi),重量为wi,有一个机器人,要按照编号从小到大的顺序剑气所有的垃圾兵扔进垃圾桶,垃圾桶在原点, 每次总重量不能超过C,两点间距离为曼哈顿距离,求出最短的 ...
- 【暑假】[深入动态规划]UVAlive 4794 Sharing Chocolate
UVAlive 4794 Sharing Chocolate 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12055 ...
- LA 3983 Robotruck
这道题感觉挺吃力的,还用到了我不熟悉的优先队列 题目中的推导也都看明白了,总之以后还要多体会才是 这里用优先对列的原因就是因为要维护一个滑动区间的最小值,比如在区间里2在1的前面,2在离开这个滑动区间 ...
- UVA LA 3983 - Robotruck DP,优先队列 难度: 2
题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...
- 2015暑假训练(UVALive 5983 - 5992)线段树离线处理+dp
A: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83690#problem/A 题意:N*M的格子,从左上走到右下,要求在每个点的权值 ...
- UVALive 3983 捡垃圾的机器人 DP
这个题目我最初的做法沿用树形DP的做法,设置一个 dp[i][0]表示机器人在i点不回去的最短路径,dp[i][1]表示机器人在i点回去的最短路径,规划方向为i-1向i转移,结果发现这个不能用树形的结 ...
- 大白第一章第四节dp例题
入口 UVALive - 3882 #include<cstdio> using namespace std; ; int n,m,k,f[N]; int main(){ //f[i]表示 ...
随机推荐
- c++ 发布动态.so
原文地址 代码改变世界 Posts - 105, Articles - 0, Comments - 1561 Cnblogs Dashboard Logout Home Contact Gallery ...
- How to Cope with Deadlocks
http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html How to Cope with Deadlocks This section ...
- ***CI异常记录到日志:CodeIgniter中设计一个全局exception hook
在CodeIgniter中,当发生异常时,经常要通知系统管理员,因此有必要在全局的高度上 捕捉异常,因此可以写一个hook, 比如在config目录的hook.php中,加入: $hook['pre_ ...
- HDU4548+素数
简单题. /* */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<alg ...
- c缺陷与陷阱笔记-第二章 语法陷阱
1.函数的调用和番薯返回值是函数指针的声明 定义一个函数指针,例如 int (*fp)(float),这个函数的返回值是Int,参数是1个float类型,调用这个函数的方法是 (*fp)(),还有f ...
- JS 封装类
function HighchartsObj(id, type) { var that = this; this.options = { chart : { renderTo : id, type : ...
- python 包管理工具pip安装与使用
pip是python的一个包管理工具,与之类似的工具还有easy_install.根据官网的说法 如果你的python版本在Python 2 >=2.7.9 or Python 3 >=3 ...
- 【.Net免费公开课】--授技.Net中的高帅富技术-"工作流"
课程简介 免费公开课主题: .Net中的高帅富技术-“工作流” 公开课开课时间: 10月17日 19:30--21:30 公开课YY频道: 85155393 (重要:公开课QQ ...
- Git教程(4)常用小技巧之标签
Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated). 一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用. 然而,附注标签是存储在 Git ...
- FastScroll(1)ListView打开FastScroll及自定义它的样式
打开 FastScroll 方式 android:fastScrollEnabled="true" 它是AbsListView的属性. <?xml version=" ...