LA3983 Robotruck


题目描述
这里写图片描述


蓝书上的例题,我重新推导一遍。
d(i) 表示捡完前 i 个垃圾需要走的最短距离。
d(i)=min{d(j)+dist0(j+1)+dist(j+1,i)+dist0(i) | w(j+1,i)<=c}
其中:
dist0(i) 表示 i 到原点的距离;
dist(i,j)表示从第 i 个垃圾走到第i+1,i+2...j个垃圾的距离;
w(i,j) 表示 i ~j个垃圾的总重量。
如果预处理出 tot_d(i) (原点依次经过1,2…i个垃圾的总距离)那么:
d(i)=min{d(j)+dist0(j+1)+tot_d(i)tot_d(j+1)+dist0(i)}
func(i)=d(i)tot_d(i+1)+dist0(i+1)
那么 d(i)=min{func(j) | w(j+1,i)<=c}+tot_d(i)+dist0(i)
单调队列维护 func(j) 可在 O(1) 时间完成转移。
代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=100010;
int d[maxn],tot_d[maxn],tot_w[maxn],dist0[maxn],q[maxn],x[maxn],y[maxn],w;
int func(int i){
    return d[i]-tot_d[i+1]+dist0[i+1];
}
int main(){
    int t;
    cin>>t;
    x[0]=y[0]=tot_w[0]=tot_d[0]=q[0]=0;;
    while(t--){
        int c,n;
        scanf("%d%d",&c,&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&x[i],&y[i],&w);
            tot_w[i]=w+tot_w[i-1];
            tot_d[i]=abs(x[i]-x[i-1])+abs(y[i]-y[i-1])+tot_d[i-1];
            dist0[i]=abs(x[i])+abs(y[i]);
        }
        int head=0,tail=1;
        for(int i=1;i<=n;i++){
            while(head<tail&&tot_w[i]-tot_w[q[head]]>c) head++;
            d[i]=func(q[head])+tot_d[i]+dist0[i];
            while(head<tail&&func(q[tail])>=func(i)) tail--;
            q[++tail]=i;
        }
        printf("%d\n",d[n]);
        if(t>0) puts("");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值