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

问题 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值