UVA1169 Robotruck

Source

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3610

Solution1

f[i][j]瞎搞一搞就行了

Solution2

刘汝佳说 O ( N C ) 会超时,然而才 10 7 啊,怎么会超时呢
f [ i ] 表示我搞完了前 i 个垃圾,并且在第 i 个位置倒垃圾的最小代价
那么
f [ i ] = m i n { f [ j ] + c o s t ( 0 , j + 1 ) + s [ i ] s [ j + 1 ] + c o s t ( i , 0 ) }
= m i n { f [ j ] s [ j + 1 ] + c o s t ( 0 , j + 1 ) } + s [ i ] + c o s t ( i , 0 )
其中 0 j < i c o s t ( 0 , j ) 表示从原点走到 j 的代价, s [ i ] c o s t ( i 1 i ) 的前缀和,这些都可以预处理,要保证 k = j + 1 i w [ k ] 不超过 C ,那这不就成了 s l i d i n g   w i n d o w 吗?
c [ j ] = f [ j ] s [ j + 1 ] + c o s t ( 0 , j + 1 )
现在方程变为 f [ i ] = m i n { c [ j ] } + ( s [ i ] + c o s t ( i , 0 ) ) , ( k < i , k = j + 1 i w [ k ] )
维护一个单调递增的双端队列,每进来一个元素,比它大的就永远不会用到,因此从队尾进去,不断踢掉那些不小于它的元素,用的时候,不断的从队首取元素,取到第一个满足 k = j + 1 i w [ k ] 即可使用它更新 f [ i ] ,不合法的直接扔掉即可
每个元素只进队列一次,出队列一次,时间复杂度 O ( n )

Code1

//动态规划
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
#define ll long long
#define clear(x) memset(x,0,sizeof(x))
#define maxn 100010
#define maxc 110
#define inf (1ll<<60)
using namespace std;
ll n, m, x[maxn], y[maxn], C, w[maxn], f[maxn][maxc];
inline ll read(ll x=0)
{
    char c, f=1;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
    return x*f;
}
inline ll d(ll a, ll b)
{
    return abs(x[a]-x[b])+abs(y[a]-y[b]);
}
void dp()
{
    ll i, j, ans=inf;
    for(i=0;i<=n+1;i++)for(j=0;j<=C;j++)f[i][j]=inf;
    f[0][0]=0;
    for(i=0;i<=n;i++)for(j=0;j<=C;j++)
    {
        f[i+1][w[i+1]]=min(f[i+1][w[i+1]],f[i][j]+d(i,0)+d(0,i+1));
        if(j+w[i+1]<=C)f[i+1][j+w[i+1]]=min(f[i+1][j+w[i+1]],f[i][j]+d(i,i+1));
    }
    for(j=1;j<=C;j++)ans=min(ans,f[n+1][j]);
    printf("%lld\n",ans);
}
int main()
{
    ll i;
    for(ll T=read();T--;)
    {
        C=read(), n=read();
        for(i=1;i<=n;i++)x[i]=read(), y[i]=read(), w[i]=read();
        dp();
        if(T)printf("\n");
    }
    return 0;
}

Code2

//单调队列优化DP
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
#define ll long long
#define cl(x) memset(x,0,sizeof(x))
#define maxn 100010
#define inf (1ll<<60)
using namespace std;
ll n, m, x[maxn], y[maxn], C, w[maxn], f[maxn], c[maxn], head, tail, s[maxn];
struct pos{ll w, c;}q[maxn];
inline ll read(ll x=0)
{
    char c, f=1;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
    return x*f;
}
inline ll d(ll a, ll b)
{
    return abs(x[a]-x[b])+abs(y[a]-y[b]);
}
void init()
{
    ll i;
    C=read(), n=read();
    for(i=1;i<=n;i++)x[i]=read(), y[i]=read(), w[i]=w[i-1]+read();
    for(i=1;i<=n;i++)s[i]=s[i-1]+d(i-1,i);
}
void DP()
{
    ll i;
    pos t;
    t=(pos){w[0],f[0]-s[1]+d(0,1)};
    q[head=tail=1,tail++]=t;
    for(i=1;i<=n;i++)
    {
        for(;w[i]-q[head].w>C;head++);      //踢掉队首不合法元素 
        f[i]=s[i]+d(i,0)+q[head].c;
        t=(pos){w[i],f[i]-s[i+1]+d(0,i+1)};
        for(;head<tail and q[tail-1].c>=t.c;tail--);
        q[tail++]=t;
    }
    printf("%d\n",f[n]);
}
int main()
{
    for(int T=read();T--;)
    {
        init();
        DP();
        if(T)printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fsahfgsadhsakndas/article/details/81105953