1. 程式人生 > >【題解】移動牛棚

【題解】移動牛棚

span pre sca 大於 min set 可能 algorithm col

這個題剛看上去我整個人都是懵的,但是真的仔細研究一下的話,還是能看出其中的線索的,建議現在對這道題一頭霧水的同學先思考一下,再回來看題解(讀題的坑好大啊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]); }

結束

【題解】移動牛棚