• [USACO2005 nov] Grazing on the Run【区间Dp】


    Online Judge:bzoj1742,bzoj1694

    Label:区间Dp

    题目描述

    John养了一只叫Joseph的奶牛。一次她去放牛,来到一个非常长的一片地,上面有N块地方长了茂盛的草。我们可以认为草地是一个数轴上的一些点。Joseph看到这些草非常兴奋,它想把它们全部吃光。于是它开始左右行走,吃草。John和Joseph开始的时候站在p位置。Joseph的移动速度是一个单位时间一个单位距离。不幸的是,草如果长时间不吃,就会腐败。我们定义一堆草的腐败值是从Joseph开始吃草到吃到这堆草的总时间。Joseph可不想吃太腐败的草,它请John帮它安排一个路线,使得它吃完所有的草后,总腐败值最小。John的数学很烂,她不知道该怎样做,你能帮她么?

    输入

    第一行两个整数N,p。表示有N处草地,奶牛初始位置为p。((N<=1000))

    接下来N行每行输入一个整数x,表示该处草地的坐标为x。((1<=x,p<=1,000,000))​

    输出

    输出一个整数,表示最小总腐败值。

    样例

    Input

    4 10
    1
    9
    11
    19
    

    Output

    44
    

    Hint

    OUTPUT DETAILS:
    Bessie can follow this route:

    • start at position 10 at time 0
    • move to position 9, arriving at time 1
    • move to position 11, arriving at time 3
    • move to position 19, arriving at time 11
    • move to position 1, arriving at time 29
      giving her a total staleness of 1+3+11+29 = 44. There are other routes
      with the same total staleness, but no route with a smaller one.

    题解

    大致题意就是,你的初始坐标为(x),你要去数轴上的(n)个点,问你到达所有点的时间总和最小是多少。

    直接贪心不可行,所以考虑dp。

    坐标什么的先离散了再说:),两点的距离可以直接预处理出来(dis[i][j]=abs(a[i]-a[j]))

    接下来考虑如何dp。

    关注到一个性质,如果到目前为止,奶牛吃过最左的草堆编号为(l),吃过最右的草堆编号为(r),则如果奶牛不是傻它肯定把([l,r])的草堆都吃过了,因为它吃草速度是瞬时的,都经过了肯定要嫖一口

    那很明显应该是个区间dp了。

    不难定义出状态(f[0/1][i][j])表示已经吃完([i,j])的草了,且现在在左端i(0),在右端j(1),所需的最少时间和

    转移根据意义模拟一下就好了,假如我现在从区间的某端(k)转移到某点(l),则花去时间为(dis[k][l]),在这个时间内除了区间([i,j]),其他所有草堆的腐败值都增加了1。

    具体转移顺序可以打个记搜。也可以直接循环转移——枚举区间长度,再枚举左端点。然后对于这道题内部再分类讨论一下处于左右端位置即可。时间复杂度为(O(N^2))

    代码如下

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1005,INF=0x3f3f3f3f;
    int a[N],dis[N][N],f[N][N][2];
    int n;
    inline void Do(int &x,int y){(x>y)&&(x=y);}
    signed main(){
    	int x;
    	scanf("%lld%lld",&n,&x);
    	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    	a[++n]=x;
    	sort(a+1,a+n+1);
    	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dis[i][j]=abs(a[i]-a[j]);
    	int st=lower_bound(a+1,a+n+1,x)-a;	
    	
    	memset(f,0x3f,sizeof(f));
    	f[st][st][0]=f[st][st][1]=0;
    	for(int i=1;i<=n;i++)for(int l=1;l+i-1<=n;l++){
    		int r=l+i-1;
    		if(f[l][r][0]<INF){
    			if(l!=1)Do(f[l-1][r][0],f[l][r][0]+dis[l-1][l]*(n-i));
    			if(r!=n)Do(f[l][r+1][1],f[l][r][0]+dis[l][r+1]*(n-i));
    		}	
    		if(f[l][r][1]<INF){
    			if(l!=1)Do(f[l-1][r][0],f[l][r][1]+dis[r][l-1]*(n-i));
    			if(r!=n)Do(f[l][r+1][1],f[l][r][1]+dis[r][r+1]*(n-i));	
    		}
    	}
    	
    	printf("%lld
    ",min(f[1][n][0],f[1][n][1]));
    }
    

    update

    本题的几个升级版

    1.SDOI2008 Sue的小球

    2.Baltic2009 beetle

  • 相关阅读:
    网络世界中的图片以及相关的处理
    Ninject 2.x细说1.基本使用
    Orchard1.4新功能自动路由(AutoRouter)并附Orchard最新1.4版汉化包
    json的一点总结
    ASP.NET MVC路由扩展:路由映射
    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(12) 网络相关操作辅助类
    IIS是如何处理ASP.NET请求的
    一周最新示例代码回顾 (3/19–3/25)
    .NET插件系统(三) 插件间通信问题——设计可自组织和注入的组装程序
    缓存总结
  • 原文地址:https://www.cnblogs.com/Tieechal/p/11637246.html
Copyright © 2020-2023  润新知