您的位置:首页 > 其它

2016暑期集训14B 奶牛逃跑 cowrun

2016-08-20 13:24 197 查看
问题 B: 奶牛逃跑

时间限制: 1 Sec 内存限制: 128 MB

题目描述

农夫约翰忘记将栅栏的一个洞修复了, 导致了他的奶牛们都逃跑了。 不仅如此, 奶牛们还都在搞破坏。 每一只在栅栏外的奶牛每分钟搞的破坏都要造成约翰 1 块钱的损失。 因此, 约翰必须去抓捕这些奶牛。 幸运的是, 奶牛们所在的位置都是在栅栏外的同一条直线上(每只奶牛的位置不同)。 约翰知道每只奶牛的位置 Pi, 当前约翰所在的位置是 0。 约翰每分钟移动一个单位的距离, 并且能够迅速的抓到所在位置的奶牛。

请帮助约翰计算他抓住这些奶牛的过程中最少会造成多少损失。

输入

第一行一个正整数 N, 表示有 N 只奶牛。

接下来 N 行, 每行一个整数 Pi, 表示第 i 只奶牛所在的位置。

输出

输出抓所有的奶牛的过程中会造成的最小损失。

样例输入

4

-2

-12

3

7

样例输出

50

提示

说明: 样例中, 抓捕奶牛的最佳顺序是-2,3,7, -12。 约翰首先花 2分钟时间抓捕在-2 位置的奶牛, 这只奶牛总共造成了 2 的损失。 然后约翰花 5 分钟的时间抓捕在位置 3 的奶牛, 这只奶牛总共造成的损失是 2+5=7。 然后他花费 4 分钟时间抓捕在位置 7 的奶牛, 这只奶牛总共造成的损失是 7+4=11,然后他花费 19 分钟的时间抓捕在位置-12上的奶牛, 这只奶牛总共造成的损失是 11+19=30。 所以, 最后的答案是 2+7+11+30=50。

【数据规模和约定】

数据范围: 1<=N<=1000, -500000<=Pi<=500000。

来源:usaco2013年3月

考试看到这道题我还是很激动的,记起在实验时做过这道题,

当时小何老师讲这是DP,我感到无助.

如今一晃一两年了,考试中我以为自己白学了,但最后还是牙齿咬住

做了出来,考试中跌宕起伏的心情,还是很爽的.

其实这题意思也很明显,向左走或向右走,我用的是记忆化,f[l,r,op]表示向左走了l次和向右走了r次,op表示0,1,在左边或右边的状态

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,le,ri,x;
int a[1005],f[1005][1005][2];
int dfs(int l,int r,int op)
{
if (l==le && r==ri) return 0;
if (f[l][r][op]!=-1) return f[l][r][op];
f[l][r][op]=1000000000;
int ret1=0,ret2=0;
if (l<le)
{
if (op==0) ret1+=(n-1-l-r)*(a[x-l]-a[x-l-1]);
else ret1+=(n-1-l-r)*(a[x+r]-a[x-l-1]);
l++;
ret1+=dfs(l,r,0);
l--;
f[l][r][op]=min(f[l][r][op],ret1);
}
if (r<ri)
{
if (op==0) ret2+=(n-1-l-r)*(a[x+r+1]-a[x-l]);
else ret2+=(n-1-l-r)*(a[x+r+1]-a[x+r]);
r++;
ret2+=dfs(l,r,1);
r--;
f[l][r][op]=min(f[l][r][op],ret2);
}
return f[l][r][op];
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
a[++n]=0;
sort(a+1,a+n+1);
x=0;
for (int i=1;i<=n;i++)
if (a[i]==0)
{
x=i;
break;
}
le=x-1,ri=n-x;
memset(f,-1,sizeof(f));
int a1=dfs(0,0,0);
int a2=dfs(0,0,1);
printf("%d\n",min(a1,a2));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DP