题解移动牛棚

Posted xiaojua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解移动牛棚相关的知识,希望对你有一定的参考价值。

这个题刚看上去我整个人都是懵的,但是真的仔细研究一下的话,还是能看出其中的线索的,建议现在对这道题一头雾水的同学先思考一下,再回来看题解(读题的坑好大啊QAQ)

那么线索是什么呢

  1. d的算式暗藏玄机,这不是一个普普通通的值,而是第1头牛在1上,第n头牛在s上时的相邻牛之间的距离

     也就是说,第一头牛必须在1上,第n头牛必须在s上

   2.相邻2头牛之间的距离要么是d(没误差),要么是d+1(有误差),这就是所谓的相邻牛距离与d之差不超过1

   3.因为有了上一条,所以我们必须有且只能有s-(n-1)*d个误差间隔

   4.因为第i-1个牛棚只可能是相隔d或d+1,所以有f[i][j]=min(f[i-1][j],f[i-1][j-1])+abs(a[i]-(i-1)*d-j),f[i][j]是前i个点中有j个误差间隔时的最优答案

读题到这里就大概有个思路了吧,接下来只要随意dp,再滚一维数组就可以了

上代码吧

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,s,d;
int a[1502],f[1502];
int main()
{
    scanf("%d %d",&n,&s);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    d=(s-1)/(n-1);
    sort(a+1,a+n+1);
    memset(f,633,sizeof(f));
    f[1]=a[1]-1;//边界,第一头牛离它本应在的位置1的距离
    for(int i=2;i<=n;i++)
    {
        for(int j=min(i,s-(n-1)*d);j>=1;j--)
      //倒着算,滚掉一维,因为我们用到的是f[i-1][j-1]和f[i-1][j],还要取个min,因为一共i个点,不能大于i,最多只需s-(n-1)*d个误差间隔 { f[j]=min(f[j-1],f[j])+abs(a[i]-(i-1)*d-j);//别忘加上当前牛离目标的距离 } } printf("%d",f[s-(n-1)*d]); }

结束


以上是关于题解移动牛棚的主要内容,如果未能解决你的问题,请参考以下文章

题解[USACO18FEB]New Barns

题解 P2701 [USACO5.3]巨大的牛棚Big Barn

[ 题解 ] [ 逆推 ] A. Taming the Herd

简题解 AWSL090429 噪音

bzoj3405:[Usaco2009 Open]Grazing2 移动牛棚

P2954([USACO09OPEN]移动牛棚Grazing2,dp)