《洛谷P3035 [USACO11DEC]Umbrellas for Cows S》

第一眼就觉得是个DP。一开始想的背包枚举对应长度时的最小代价。

但是这样复杂度是N*M,显然会T。

正解:不需要去考虑凑成长度的最优代价。

用dp[i]来表示到把到i包括i的牛全覆盖掉的最小代价。

那么对于每一个i,我们去枚举转移的位置j,这样最优的方案里会包括上最优的组合法(包括重复选同一个)

那么转移很明显,主要的是,可能更大的长度它的价值更小,且长度更大,那么更新为它即可。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 5e3+5;
const int M = 1e5+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline int read(){  
        int x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;
void FRE(){
/*freopen("data1.in","r",stdin);
freopen("date1.out","w",stdout);*/}
//P3035 [USACO11DEC]Umbrellas for Cows S

LL x[N],c[M];
LL dp[N];//把到第i只牛覆盖进去的最小代价
int main()
{
    int n,m;n = read(),m = read();
    for(rg int i = 1;i <= n;++i) x[i] = read();
    fill(dp,dp+N-1,INF);
    sort(x+1,x+n+1);
    for(rg int i = 1;i <= m;++i) c[i] = read();
    for(rg int i = m-1;i >= 1;--i) c[i] = min(c[i],c[i+1]);
    dp[0] = 0;
    dp[1] = c[1];
    for(rg int i = 2;i <= n;++i)
    {
        int ma = x[i]-x[i-1];
        for(rg int j = 1;j <= i;++j) dp[i] = min(dp[i],dp[j-1]+c[x[i]-x[j]+1]);
    }
    printf("%lld\n",dp[n]);
    system("pause");     
    return 0;
}

/*
3 4
2 4 5
3 3 5 7 15 18
*/
View Code
原文地址:https://www.cnblogs.com/zwjzwj/p/13529668.html