UVALive - 3983 Robotruck DP

题目大意:有n个垃圾,第i个垃圾的坐标是(xi.yi),重量为wi。现有一个机器人,要按照编号从小到大的顺序捡起所有垃圾并放回垃圾桶,机器人的最大载重量为C,两点之间的距离为曼哈顿距离,求机器人行走的最短总路程

解题思路:用dp[i]表示捡到第i个垃圾回到原点所需要走的路程,dist[i]表示从原点走到第i点所需走的路程,len[i][j]表示从第i个点按顺序走到第j个点所需走的路程

由这几个,可以推出转换方程:dp[j] = dp[i] + len[i+1][j] + dist[i+1] + dist[j](前提是从第i+1个点按顺序到第j个点所捡的垃圾的总重量不大于C)

再假设total_dist[i]为从第1个垃圾按顺序捡到第i个垃圾所需要走的路程,则len[i+1][j] = total_dist[j] - total_dist[i+1],那么dp[j] = min(dp[i] - total_dist[i+1] + dist[i+1]) + dist[j] + total_dist[j]

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 100010
int len[maxn], dist[maxn], dp[maxn], x[maxn], y[maxn], weight[maxn], que[maxn];
int count(int cur) {
	return dist[cur + 1] + dp[cur] - len[cur+1]; 
}

int main() {
	int test, c, n, t, front, rear;
	scanf("%d",&test);
	while(test--) {
		scanf("%d%d",&c,&n);
		que[0] = x[0] = y[0] = dp[0] = dist[0] = len[0] = weight[0] = 0;
		for(int i = 1; i <= n; i++) {
			scanf("%d%d%d",&x[i],&y[i], &t);
			dist[i] = abs(x[i]) + abs(y[i]);
			weight[i] = weight[i-1] + t;	
			len[i] = len[i-1] + abs(x[i] -x[i-1]) + abs(y[i] - y[i-1]);
		}
		front = rear = 1;
		for(int i = 1; i <= n; i++) {
			while(front <= rear && weight[i] - weight[que[front]] > c)
				front++;
			dp[i] = count(que[front]) + len[i] + dist[i];	
			while(front <= rear && count(i) <= count(que[rear]))
				rear--;
			que[++rear] = i;
		}
		printf("%d\n",dp[n]);
		if(test)
			printf("\n");
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值