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;
}
完结撒花~
浙公网安备 33010602011771号