zoukankan      html  css  js  c++  java
  • UVA1169 Robotruck

    Dp+优化

    首先我们考虑暴力怎么写?dp[i]表示选到i号辣鸡并将其放回的最优解,那么令dis[i]表示从1走到i的曼哈顿距离之和,from[i]表示从(0,0)走到i的曼哈顿距离,那么

    [dp[i]=min(dp[i],dp[j]+dis[i]-dis[j+1]+from[j+1]+from[i]); ]

    [0<=j<=i-1 ]

    我们移项:
    (dp[i]=min(dp[i],dp[j]-dis[j+1]+from[j+1]+dis[i]+from[i]);)

    $ 0<=j<=i-1 $

    显然,$$dp[j]-dis[j+1]+from[j+1]$$ 可以用线段树单调队列维护。

    然后这道题就愉快的结束了(我用了线段树)

    注意要换行!!!!

    送大家一组样例,这组样例卡掉了一个CSDN的标程

    in:

    5
    77
    9
    9 26 38
    38 1 44
    26 28 72
    38 37 29
    2 7 27
    14 20 9
    21 13 45
    25 32 33
    10 4 41
    17
    1
    3 1 12
    43
    3
    37 10 36
    30 32 31
    18 5 13
    36
    5
    14 23 33
    2 18 5
    33 8 13
    6 31 13
    13 21 25
    76
    5
    27 2 61
    32 41 41
    16 37 17
    34 40 9
    37 26 49
    
    

    out

    602
    
    8
    
    264
    
    290
    
    358
    
    
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define half (l+r)>>1
    using namespace std;
    const int maxn=100006;
    inline int abs_(int x,int y)
    {
        return x>y?x-y:y-x;
    }
    int x[maxn],y[maxn],w[maxn],from[maxn],cost[maxn],dp[maxn],n,sum[maxn];
    struct hzw
    {
        int lc,rc,mx;
    }t[maxn*5];
    int tot;
    inline void build(int s,int l,int r)
    {
        if(l==r)
        {
            t[s].mx=0x3f3f3f3f;
            return;
        }
        int mid=half;
        t[s].lc=++tot;
        build(tot,l,mid);
        t[s].rc=++tot;
        build(tot,mid+1,r);
    }
    inline void update(int s,int l,int r,int p,int x)
    {
        if (l==p&&r==p)
        {
            t[s].mx=x;
            return;
        }
        int mid=half;
        if (p<=mid) update(t[s].lc,l,mid,p,x);
        else update(t[s].rc,mid+1,r,p,x);
        t[s].mx=min(t[t[s].lc].mx,t[t[s].rc].mx);
    }
    inline int query(int s,int l,int r,int cl,int cr)
    {
        if (l==cl&&r==cr)
        {
            return t[s].mx;
        }
        int mid=half;
        if (cr<=mid) return query(t[s].lc,l,mid,cl,cr);
        else if (cl>mid) return query(t[s].rc,mid+1,r,cl,cr);
        else
        return min(query(t[s].lc,l,mid,cl,mid),
        	       query(t[s].rc,mid+1,r,mid+1,cr));
    }
    inline int search(int ll,int rr,int k)
    {
        int l=ll,r=rr,ans=rr;
        while (l<=r)
        {
            int mid=half;
            if (cost[rr]-cost[mid-1]<=k)
            {
                r=mid-1;
                ans=min(ans,mid);
            }
            else l=mid+1;
        }
        return ans;
    }
    int main()
    {
    //	freopen("data.in","r",stdin);
    //	freopen("baoli.out","w",stdout);
        int gg,maxx;
        cin>>gg;
        while (gg--)
        {
            memset(dp,0x3f,sizeof(dp));
            tot=1;
            cin>>maxx;
            scanf("%d",&n);
            build(1,0,n);
            for (int i=1;i<=n;++i)
            {
                scanf("%d%d%d",&x[i],&y[i],&w[i]);
                from[i]=x[i]+y[i];
                if (i>1) 
                sum[i]=sum[i-1]+abs_(x[i],x[i-1])+abs_(y[i],y[i-1]);
                cost[i]=cost[i-1]+w[i];
            }
        	dp[0]=0;
        	dp[1]=2*from[1];
    		update(1,0,n,0,from[1]);
    		update(1,0,n,1,from[2]-sum[2]+dp[1]);
    		for (int i=2;i<=n;++i)
    		{
    			int wh=search(0,i,maxx);
    			wh=max(0,wh-1);
    			dp[i]=query(1,0,n,wh,i-1)+sum[i]+from[i];
    			update(1,0,n,i,from[i+1]-sum[i+1]+dp[i]);
    		}
    		cout<<dp[n]<<endl;
    		if (gg!=0)cout<<endl;
        }
        return 0;
    }
    

    收获:我们一定要先写出最裸的dp方程,再考虑优化

  • 相关阅读:
    vs2019编译错误:Exception Processing Message 0xc0000005 Parameters...
    error LNK2001
    Debug Assertion Failed
    对路径“………………”的访问被拒绝
    c语言打开文件为什么总是以二进制方式打开
    关于typedef的用法总结
    xml学习第一天
    关于VS2017编译成功系统找不到指定文件.exe的问题
    引入的外部js文件在html文件在浏览器中乱码显示
    结对作业(四则运算)
  • 原文地址:https://www.cnblogs.com/bullshit/p/9755550.html
Copyright © 2011-2022 走看看