LA3983 Robotruck --- dp+优先队列

题意: 给n个垃圾的(n<100000)坐标x,y,每个垃圾一个重量,给定一个机器人,可以承重C,机器人从原点出发,要求按照顺序依次将1-n的垃圾回收到原点,求最小路程?

题解: 动态规划思路,di = min(dj+H(j+1)+Sumi-Sumj+1+Hi), di表示将前i个垃圾回收到原点的最短路程,Sum[i]表示从垃圾1依次走到垃圾i的路程,Hi表示i号垃圾到原点的曼哈顿距离(即x与y坐标差的绝对值和),遍历的时候维护下dj+H[j+1]-Sum[j+1]的最小值即可,不维护的话时间复杂度是n^2,用优先队列维护后应该是线性时间复杂度,网上的题解看似乎也可以用单调队列

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define MAXN 100010
using namespace std;
int C,n;
int x[MAXN],y[MAXN],c[MAXN];
int H[MAXN],HSum[MAXN],CSum[MAXN];
int dp[MAXN];
struct Node {
  int value,index;
  bool operator < (const Node &n) const {
    return value > n.value;
  }
};
priority_queue<Node> q;

void Init() {
  memset(H,0,sizeof(H));
  memset(HSum,0,sizeof(HSum));
  memset(dp,0,sizeof(dp));
  while(!q.empty()) q.pop();
}

// di = dj+H(j+1)+Sumi-Sumj+1+Hi
int main() {
  int T;
  scanf("%d",&T);
  while(T--) {
    Init();
    scanf("%d%d",&C,&n);
    for(int i = 1;i <= n;i++) {
      scanf("%d%d%d",&x[i],&y[i],&c[i]);
      H[i] = abs(x[i]) + abs(y[i]);
      HSum[i] = (i==1?H[1]:HSum[i-1]+abs(x[i]-x[i-1])+abs(y[i]-y[i-1]));
      CSum[i] = (i==1?c[1]:c[i]+CSum[i-1]);
    }
    for(int i = 1;i <= n;i++) {
     int t = dp[i-1]+H[i]-HSum[i];
     q.push((Node){t,i-1});
     while(!q.empty()) {
       Node node = q.top();
       int j = node.index;
       if(CSum[i] - CSum[j] > C) {
         q.pop();
         continue;
       }
       dp[i] = node.value + HSum[i] + H[i];
       break;
     }
    }
    printf("%d\n",dp[n]);
    if(T) printf("\n");
  }

  return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值