1. 程式人生 > 實用技巧 >P3035 [USACO11DEC]Umbrellas for Cows S(DP)

P3035 [USACO11DEC]Umbrellas for Cows S(DP)

Solution

很容易看出本題是用dp解的,所以我們設 \(f[i]\) 表示前 \(i\) 個覆蓋所需的最小价值。

易得: \(f[i]=\min(f[i],f[j-1]+cost[a[i]-a[j]+1])\)

其中 \(a[i]\) 為第 \(i\) 個點的位置, \(cost[i]\) 表示長度為 \(i\) 的線段的價格

但是,因為長度越長的線段價格不一定越高並且長度長的可以覆蓋短的,所以我們在 $cost[a[i]-a[j]+1] $ ~ \(cost[m]\) 選一個最小的即可,為了防超時,可預處理一個字尾最小值陣列。

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int N=200005;
int n,m,f[N],cost[N],a[N],v[N];

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    return x*f;
}

int main(){
    n=read();m=read();
    memset(f,63,sizeof(f));f[0]=0;
    for(int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+n+1);
    for(int i=1;i<=m;i++) v[i]=read();
    v[0]=1<<30,cost[m+1]=1<<30;
    for(int i=m;i>=0;i--) cost[i]=min(v[i],cost[i+1]);
    for(int i=1;i<=n;i++)
        for(int j=i;j;j--)
            f[i]=min(f[i],f[j-1]+cost[a[i]-a[j]+1]);
    printf("%d\n",f[n]);
    return 0;
}