LA 3983 Robotruck DP解法 代码+一点注释

原题:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1984

表示我一开始也是想到那个O(CN)的解法

其实思路在白皮书上面都写的挺清楚了,可以参考算法竞赛入门经典训练指南上面的

就说说最后那个 que[++front]=i 那里为啥这么写可以吧

那里目的是新来的插入队列的时候插入一个位置使得队列仍然是单调队列,也就是插入的时候只有找到一个比自己小的或者找到头了才能插进去。插入之后需要删除比它大的队列,这里以改代删,因为使得front增加的只有最后一句,而最后一句又是修改句,所以比它大的数必然会被覆盖。

#include<bits/stdc++.h>
using namespace std;
const int maxn1 = 105;
const int maxn2 = 100005;
long long dp[maxn2], dis_bet[maxn2], dis_bac[maxn2], total_wei[maxn2];
// dis_bet:dis_between 点1~点n的距离    dis_bac: dis_back 1~n点到0分别的距离
int c, n;
long long MIX(int j) {
	return dp[j] - dis_bet[j + 1] + dis_bac[j + 1];
}
int main() {
	int T; cin >> T;
	while (T--) {
		memset(dp, 0, sizeof(dp));
		scanf("%d", &c);
		scanf("%d", &n);
		int p1,p2,wei,p11=0,p22=0;
		dis_bet[0]=dis_bac[0] = total_wei[0] = 0;
		for (int i = 1; i <= n; i++) {
			scanf("%lld %lld %lld", &p1, &p2, &wei);
			if(i!=1) dis_bet[i] = dis_bet[i - 1] + abs(p1 - p11) + abs(p2 - p22);
			dis_bac[i] = p1 + p2;
			total_wei[i] = total_wei[i - 1] + wei;
			p11 = p1; p22 = p2;
		}
		int que[maxn2]; // que【j】表示j到i中MIX最小的坐标
		//队列方向:     back  ----------> front
		memset(que, 0, sizeof(que));
		int front = 1, back = 1;
		for (int i = 1; i <= n; i++) {
			while (back <= front && total_wei[i] - total_wei[que[back]] > c) back++; 
			dp[i] = MIX(que[back]) + dis_bet[i] + dis_bac[i];
			while (front >= back && MIX(i) <= MIX(que[front])) front--;	  //将新来的插进队列中,保持单调队列
			que[++front] = i; 
		}
		printf("%lld\n", dp[n]);
		if (T > 0) printf("\n");
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值