CF988F Rain and Umbrellas

思路

首先要观察出一个结论:虽然不限制同时持有雨伞的数量,但最优解中 Polycarp 一定不存在某一时刻同时持有两把伞。

考虑设计 \(dp_{ i , j }\) 表示在点 \(i\) 处持有第 \(j\) 把伞的方案数,其中 \(j = 0\) 时不持有任何一把雨伞。对于 \(dp_{ i , j }\) 往后的转移:

  • 如果此处没有下雨,则可以不持有雨伞,也就不产生额外花费:\(dp_{ i + 1 , 0 } = \min ( dp_{ i + 1 , 0 } , dp_{ i , j } )\)

  • 如果此时持有雨伞,则可以保留手中雨伞:\(dp_{ i + 1 , j } = \min ( dp_{ i + 1 , j } , dp_{ i , j } + cost_j )\)

  • 如果这个位置有新的雨伞,则可以选择更换,令 \(ind\) 表示点 \(i\) 处的雨伞编号:$ dp_{ i + 1 , ind } = \min ( dp_{ i + 1 , ind } , dp_{ i , j } + cost_{ind} )$

最后在 \(dp_{ a , 0 } \sim dp_{ a , m }\) 之间取一个最小值即可。

Code

#include<iostream>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N=2005;
int a,n,m,diff[N],avo[N],ind[N],dp[N][N],ans=0x3f3f3f3f;
bool vis[N];
int main()
{
    // freopen("bead.in","r",stdin);
    // freopen("bead.out","w",stdout);
    IOS;
    cin>>a>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int L,R;
        cin>>L>>R;
        diff[L+1]++,diff[R+1]--;
    }
    for(int i=1,sum=0;i<=a;i++)
        sum+=diff[i],vis[i]=(sum>0);
    avo[0]=0x3f3f3f3f;
    for(int i=1,pos;i<=m;i++)
    {
        cin>>pos>>avo[i];
        if(avo[i]<avo[ind[pos]])
            ind[pos]=i;
    }
    for(int i=0;i<N;i++)    
        for(int j=0;j<N;j++)
            dp[i][j]=0x3f3f3f3f;
    dp[0][0]=0;
    for(int i=1;i<=a;i++)
    {
        for(int j=0;j<=m;j++)
        {
            if(!vis[i]) dp[i][0]=min(dp[i][0],dp[i-1][j]);
            if(j>0) dp[i][j]=min(dp[i][j],dp[i-1][j]+avo[j]);
            if(ind[i-1]) dp[i][ind[i-1]]=min(dp[i][ind[i-1]],dp[i-1][j]+avo[ind[i-1]]);
        }
    }
    for(int i=0;i<=m;i++)
        ans=min(ans,dp[a][i]);
    if(ans==dp[0][1]) ans=-1;
    cout<<ans<<'\n';
    return 0;
}

完结撒花~

posted @ 2025-11-13 12:03  FallingGardenia  阅读(22)  评论(0)    收藏  举报