zoukankan      html  css  js  c++  java
  • BZOJ1742[Usaco2005 nov]Grazing on the Run

    Description

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

    Input

    * Line 1 : Two space-separated integers: N and L. N<=1000
    * Lines 2..N+1: Each line contains a single integer giving the position P of a clump (1 <= P <= 1,000,000).

    Output

    * Line 1: A single integer: the minimum total staleness Bessie can achieve while eating all the clumps.

    Sample Input

    4 10
    1
    9
    11
    19
    INPUT DETAILS:
    Four clumps: at 1, 9, 11, and 19. Bessie starts at location 10.

    Sample Output

    44
    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.44
    题解:这道题因为牛一直在左右走,所以全部吃完后牛一定停在最左边的那块草地或最右边的那块草地,同样的是,对于区间i草地到j草地来说,当牛吃完这块草地的时候,它一定停在i草地或j草地上,我们用f[i][j][0]表示牛吃完区间i到j,并停在i草地所得的腐烂值,f[i][j][1]表示停在j草地所得的腐烂值。a储存每块草地的位置。
    为了后面的计算方便,我们把牛的最初位置也算作一块草地,只不过f[i][i][0]=f[i][i][1]=0,是没有值的。所以n在一开始会加上1。
    则动态转移方程为:

       f[i][j][0]=min(f[i+1][j][0]+(a[i+1]-a[i])*(n-j+i),f[i+1][j][1]+(a[j]-a[i])*(n-j+i));
       f[i][j][1]=min(f[i][j-1][0]+(a[j]-a[i])*(n-j+i),f[i][j-1][1]+(a[j]-a[j-1])*(n-j+i));

    首先我们先看第一个式子 f[i][j][0]=min(f[i+1][j][0]+(a[i+1]-a[i])*(n-j+i),f[i+1][j][1]+(a[j]-a[i])*(n-j+i));

    f[i][j][0]表示牛吃完区间i到j,并停在i草地所得的腐烂值,那说明i草地是这块区间内最后被吃的,即在这之前i+1到j块草地已经被吃过了,且牛停在i+1块草地或是j块草地上,

    当它之前停在i+1块草地上时,即之前的腐烂值为f[i+1][j][0]时,我们只需在之前的腐烂值上,加上第i+1块草地到第i块草地,所会带来的总腐烂值,就是现在的答案啦。

    那么什么是所会带来的总腐烂值呢?当牛从i+1到i时,所需经过的路程为a[i+1]-a[i],即之后吃的每块草地都需加上这个腐烂值,总共有n-j+i(这个值是把牛最初的位置也当成一块草地的前提下推出来的,就是n-(j-i))块草地未被吃,所以之后总共要增加的腐烂值为(a[i+1]-a[i])*(n-j+i),总腐烂值就是f[i+1][j][0]+(a[i+1]-a[i])*(n-j+i),我们再把它和牛之前停在第j块草地上所需增加的腐烂值进行比较,取较小的就是f[i][j][0]的值。

    第二个式子也是差不多的,可以自己去推一下。

    还有一点,让我错了5次,就是一开始f[i][i][0]和f[i][i][1]是不能全部都算作无限大的,而应该赋值为它与牛初始位置之差并乘上n,即一开始就只吃那块草地所会为其他草地带去的腐烂值。

    记得排序!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int n,l,j,a[2000],f[2000][2000][2];
    int main()
    {
      cin>>n>>l;
      for (int i=1;i<=n;i++) cin>>a[i];
      a[n+1]=l;
      n+=1;
      sort(a+1,a+1+n);
      for (int i=1;i<=n;i++)
      f[i][i][0]=f[i][i][1]=abs(a[i]-l)*n;//这里的初始化一定要小心!
      for (int len=2;len<=n;len++)
       for (int i=1;i<=n-len+1;i++)
       {
            j=i+len-1;
            f[i][j][0]=min(f[i+1][j][0]+(a[i+1]-a[i])*(n-j+i),f[i+1][j][1]+(a[j]-a[i])*(n-j+i));//吃完i到j这个区间并停在i所获的最小腐烂值
            f[i][j][1]=min(f[i][j-1][0]+(a[j]-a[i])*(n-j+i),f[i][j-1][1]+(a[j]-a[j-1])*(n-j+i));//这个是停在j的
    //奇怪的方程。。。在前面写过意思了
       }  
       cout<<min(f[1][n][1],f[1][n][0])<<endl;//输出最优解。
       return 0;
    }
  • 相关阅读:
    google protobuf ios开发使用
    iOS下载使用系统字体
    xcode7 打开工程错误 This Document requires xcode8.0 or later.
    mac 文本编辑器 文本编码Unicode utf-8 不适用的问题
    iOS中JS 与OC的交互(JavaScriptCore.framework)
    cookie 设置报错 setcookie() expects parameter 3 to be integer, float given in...
    wordpress 获取指定作者或者文章的所有评论数量
    HTML a标签链接 设置点击下载文件
    PHPUnit 单元测试教程
    phpstudy 首次安装后打开网站 数据库内容 中文乱码
  • 原文地址:https://www.cnblogs.com/2014nhc/p/6233556.html
Copyright © 2011-2022 走看看