UVA 1169 Robotruck

dp[i] 表示從原點出發,將前i個垃圾處理的最小距離

dis[i] 表示從原點一直到第i個的總距離   所以  dis[i]-dis[j+1] 表示從第就j+1 到 i 的距離    odis[i] 表示第i個到原點的距離,w[i] 表示前i個的質量之和 

dp[i]=  min(dp[j]+odis[j+1]+dis[i]-dis[j+1]+odis[i] )     j<=i    w[i]-w[j]<=c

令cal( j) =  dp[j]-dis[j+1]+odis[j+1]  

單調隊列q  維護的  是  cal(q[ ]) 單調遞增

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
typedef long long lld;
typedef unsigned long long ull;
const int maxn = 100010;
int n,c;
int dp[maxn],w[maxn],dis[maxn],x[maxn],y[maxn],odis[maxn];
int q[maxn];
int f,r;
int cal(int i)
{
    return dp[i]-dis[i+1]+odis[i+1];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&c,&n);
        dis[0]=0;w[0]=0;
        x[0]=0;y[0]=0;
        for(int i=1;i<=n;i++)
        {
            int z;
            scanf("%d %d %d",&x[i],&y[i],&z);
            dis[i]=dis[i-1]+abs(x[i]-x[i-1])+abs(y[i]-y[i-1]);
            w[i]=w[i-1]+z;
            odis[i]=x[i]+y[i];
        }
        f=r=1;
        q[1]=0;
        for(int i=1;i<=n;i++)
        {
            while(f<=r&&w[i]-w[q[f]]>c) f++;
            dp[i]=cal(q[f])+dis[i]+odis[i];
            while(f<=r&&cal(i)<=cal(q[r])) r--;
            q[++r]=i;
        }
        printf("%d\n",dp[n]);
        if(T>0) puts("");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章