您的位置:首页 > 其它

[bzoj1742][Usaco2005 nov][DP]Grazing on the Run 边跑边吃草

2017-11-02 11:09 399 查看
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

题解

其实这个翻译和usaco真的太不一样了。。

设f[i][j][0]和f[i][j][1]分别为i~j吃完 停在i和i~j吃完 停在j的最小腐败值

想了一早上N^3的做法。。就是枚举长度+起始点+断点

这样的话终点就可以根据起点+长度算出,但是好像是N^3方的做法。。

??????结果发现直接N^2就可以了。

因为每个f[i][j]继承的都是离他最近的那个草堆,所以说完全不用枚举断点。。

这样方程就变成了

f[x][y][0]=min(f[x+1][y][0]+(d[x+1]-d[x])(n-y+x),f[x+1][y][1]+(d[y]-d[x])(n-y+x));

f[x][y][1]=min(f[x][y-1][0]+(d[y]-d[x])(n-y+x),f[x][y-1][1]+(d[y]-d[y-1])(n-y+x));

为什么要乘(n-y+x)??因为(y-x)是x+1到y的草地数,这一段已经吃完了

然后除了这些的,其他都会被影响到,被影响了的草地数就是n-(y-x)

这样,就乘起来再加上。。

哦,空间卡的有点紧,可以考虑一下滚动。我懒就不搞了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int f[1100][1100][2];//吃完了第i~j堆草 停在i/j边
int n,k;
int d[1100];
int main()
{
memset(f,63,sizeof(f));
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&d[i]);
sort(d+1,d+1+n);
for(int i=1;i<=n;i++)f[i][i][0]=f[i][i][1]=abs(d[i]-k)*n;
for(int i=2;i<=n;i++)//枚举长度
{
for(int x=1;x<=n-i+1;x++)
{
int y=x+i-1;
f[x][y][0]=min(f[x+1][y][0]+(d[x+1]-d[x])*(n-y+x),f[x+1][y][1]+(d[y]-d[x])*(n-y+x));//(n-y+x)为还没有吃到的草地,对他们自然有影响
f[x][y][1]=min(f[x][y-1][0]+(d[y]-d[x])*(n-y+x),f[x][y-1][1]+(d[y]-d[y-1])*(n-y+x));
}
}
printf("%d\n",min(f[1]
[0],f[1]
[1]));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: