题目地址:http://vjudge.net/problem/UVALive-3983
d[i]表示从原点出发,经过前i个点,且回垃圾桶倒垃圾的最短路径
#include <bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=a;i<=(b);++i)
#define REPD(i,a,b) for(int i=a;i>=(b);--i)
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define func(i) (d[i]-totalDist[i+1]+dist(i+1,0))
const int maxn=100000+5;
int x[maxn],y[maxn],w[maxn];
int totalDist[maxn],q[maxn],d[maxn],totalWeight[maxn];
int dist(int i,int j){
return abs(x[i]-x[j])+abs(y[i]-y[j]);
}
int main(int argc, char const *argv[])
{
int T; scanf("%d",&T);
while(T--){
int C,n; scanf("%d%d",&C,&n);
REP(i,1,n) {
scanf("%d%d%d",&x[i],&y[i],&w[i]);
totalDist[i]=totalDist[i-1]+dist(i,i-1);
totalWeight[i]=totalWeight[i-1]+w[i];
}
int front=1,rear=1;
REP(i,1,n){ //rear~front 中维护一个W(rear~front)<=C 且func()递增队列
while(rear<=front&&totalWeight[i]-totalWeight[q[rear]]>C) rear++;
d[i]=func(q[rear])+totalDist[i]+dist(i,0);
while(rear<=front&&func(i)<=func(q[front])) front--; //队列中删去比i大的
q[++front]=i; //添加i
}
printf("%d\n", d[n]);
if(T) printf("\n");
}
return 0;
}