UVA 1169 Robotruck 单调队列优化 DP

该博客介绍了如何解决UVA 1169问题,即在平面上捡拾垃圾的机器人路径规划。问题中,机器人从原点出发,按顺序捡拾具有重量限制的垃圾,目标是最小化返回原点的总距离。博主提出使用动态规划(DP)和单调队列进行优化,以达到O(N)的时间复杂度。博客内容包括问题定义、解题思路和代码实现。
摘要由CSDN通过智能技术生成

题意:在平面上有N个垃圾,告诉每个垃圾的坐标。现在有一个机器人从原点出发,按照给定的顺序把垃圾捡回来。同时每个垃圾都有重量,机器人有最大装载重量C。垃圾之间和垃圾和原点之间的距离定义为两点坐标的曼哈顿距离。现在求最少的距离,使机器人完成这件任务。

思路:看到N=100000,就该去想O(N)的算法了。这里我们用DP来求解。

            设dp[i]表示捡完前i个垃圾,并回到原点的最少距离。

            我们可以得到递推式:dp[i] = min(dp[k] - dis[k] + ds[i] - ds[k] + dis[i]), ws[i] - ws[k] <= C,其中dis[i]表示第i个垃圾到原点的距离,ds[i]表示前i个垃圾的距离的和,ws[i]表示前i个垃圾的总重量。

          我们可以看到,dis[i],ds[i]是和k无关的项,变形得:dp[i] = min(dp[k] - dis[k] - ds[k]) + ds[i] + dis[i] ,ws[i] -ws[k] <= C.这就转化成了求前面一项的最小值。再次,我们发现,前面一项也只是和k有关,而对于固定的k,这也是个定值。这样,我们就能用单调队列优化,在队列的头保存最小值。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 100100;
int x[MAXN], y[MAXN], w[MAXN];
int dist[MAXN], sumw[MAXN], dis[MAXN];
int q[MAXN], dp[MAXN];

int func(int i)
{
	return dp[i] - dist[i + 1] + dis[i + 1];
}
int main()
{
	//freopen("input.txt", "r", stdin);
	int T;
	int C, N, head, tail;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d %d", &C, &N);
		dist[0] = dis[0] = 0;
		for (int i = 1; i <= N; i++)
		{
			scanf("%d %d %d", &x[i], &y[i], &w[i]);
			dist[i] = dist[i - 1] + abs(x[i] - x[i - 1]) + abs(y[i] - y[i - 1]);
			dis[i] = abs(x[i]) + abs(y[i]);
			sumw[i] = sumw[i - 1] + w[i];
		}
		head = tail = 0;
		q[tail++] = 0; 
		for (int i = 1; i <= N; i++)
		{
			while (head + 1 < tail && sumw[i] - sumw[q[head]] > C)
				head++;
			dp[i] = func(q[head]) + dis[i] + dist[i];
			while (head + 1 < tail && func(i) <= func(q[tail-1]))
				tail--;
			q[tail++] = i;
		}
		//for (int i = 1; i <= N; ++i)
			printf("%d\n", dp[N]);
		if (T)
			puts("");
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值