您的位置:首页 > 其它

uva1169 - Robotruck

2016-02-13 12:55 281 查看
题意:

n个垃圾,有其坐标(x,y)即重量w,一机器人最多承受重量C,要按其编号依次去捡垃圾(它只能上下左右走)然后倒垃圾,垃圾桶在原点(0,0),求倒完所有垃圾需走的最小距离。

思路:

直接dp的话复杂度O(100000*100)过大,因而用单调队列来优化。

dp[i]表示倒前i个垃圾的最小距离,sumd[i]表示前i个垃圾的曼哈顿距离,sumw[i]表示前i个垃圾的重量和,p[i].d表示i到原点的曼哈顿距离。

dp[i]=dp[j]+sumd[i] - sumd[j + 1] + p[j + 1].d+p[i].d.

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;

const int N = 100005;
int w, n, sumw
, sumd
, dp
;

struct point {
int x, y, w, d;
}p
, zero;

int dis(point a,point b) {
return abs(a.x - b.x) + abs(a.y - b.y);
}
int func(int j) {
return dp[j] - sumd[j + 1] + p[j + 1].d;
}
int solve(){
deque<int> Q;//用单调队列控制滑动窗口func的最小值
Q.push_front(0); //dp[i]=min{func(j)|w(j+1,i)<w)+sumd[i]+p[i].d
for (int i = 1; i <= n; i++) {
while (!Q.empty() && sumw[i] - sumw[Q.front()] > w)  {
Q.pop_front();
}
dp[i] = func(Q.front()) + sumd[i] + p[i].d;
while (!Q.empty()&&func(i)<=func(Q.back())) {
Q.pop_back();
}
Q.push_back(i);
}
return dp
;
}
int main() {
int cas;
scanf("%d",&cas);
while (cas--) {
memset(p, 0, sizeof(p));
memset(sumw, 0, sizeof(sumw));
memset(sumd, 0, sizeof(sumd));
scanf("%d%d", &w, &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].w);
sumw[i] = sumw[i - 1] + p[i].w;
sumd[i] = sumd[i - 1] + dis(p[i], p[i - 1]);
p[i].d = dis(p[i], zero);
}
printf("%d\n", solve());
if (cas)
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: