题目链接:uva1169
题意:有一个机器人要按照编号从小到大的顺序捡起所有垃圾并扔进垃圾桶,可以一次捡起几个,但不能超过最大载重,求最短总路程。
根据大白书上写的,d[i]=min(d[j]-total_dist[j+1]+dist2origin[j+1])+total_dist[i]+dist2origin[i];
所以我们要找到func(j)=d[j]-total_dist[j+1]+dist2origin[j+1]的最小值
如果走到当前点i能走到队列中哪个点,队列中最小的走不到,就把最小的出队,然后继续判断(这个队列是递增的),一直找到能够走到了,这时的func一定最小(走到前一个点肯定比后一个点小),进入队列时把比这个元素大的全部删掉,这个比其他的元素小,所以当然不会用其他的元素。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN=100010;
int x[MAXN],y[MAXN],total_dist[MAXN],total_weight[MAXN],dist2origin[MAXN];
int q[MAXN],d[MAXN];
int func(int i)
{
return d[i]-total_dist[i+1]+dist2origin[i+1];
}
int main()
{
int i,t,c,n,w,front,rear;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&c,&n);
total_dist[0]=total_weight[0]=x[0]=y[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&w);
dist2origin[i]=abs(x[i])+abs(y[i]);
total_dist[i]=total_dist[i-1]+abs(x[i]-x[i-1])+abs(y[i]-y[i-1]);
total_weight[i]=total_weight[i-1]+w;
}
front=rear=1;
for(i=1;i<=n;i++)
{
while(front<=rear&&total_weight[i]-total_weight[q[front]]>c)
front++;
d[i]=func(q[front])+total_dist[i]+dist2origin[i];
while(front<=rear&&func(i)<=func(q[rear]))
rear--;
q[++rear]=i;
}
printf("%d\n",d[n]);
if(t)
printf("\n");
}
return 0;
}