本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
【Codeforces】Codeforces Round #486 (Div. 3) F. Rain and Umbrellas | 动态规划
题目链接
题目
题目大意
Polycarp 住在数轴的 点,他去找住在 点的朋友。他只能从左向右移动,每秒可以通过一个单位的长度。有 个关于下雨路段的描述,第 个描述 表示从数轴的 点到 点的线段上在下雨。所有关于下雨路段的描述不相交。在 Polycarp 去找住在 点的朋友的路上有 把伞,第 把伞位于点 并且具有重量 。最初 Polycarp 没拿着伞。
在途中的任一个点上,Polycarp 可以捡起或扔掉雨伞。Polycarp 可以携带任何数量的雨伞。因为Polycarp 不想淋湿,所以当他从 移动到 时,如果 [x,x+1] 在雨中,他必须拿着伞。他可以不带雨伞到一个开始下雨的地方,在这个地方拿起一把雨伞,带着雨伞前进。
Polycarp 最初的疲劳度是 0,他每拿着重量为 的雨伞前进 1 个单位长度,他的疲劳度增加 。
如果 Polycarp 可以在不淋雨的前提下到达他朋友家,最小化 Polycarp 的疲劳度。否则输出 -1。
思路
表示 Polycarp 从点 在不淋雨的前提下到达他朋友家的最小疲劳度。则:
- 如过当前位置没有伞,当前位置有雨,无法到达,。
- 如过当前位置没有伞,当前位置无雨,可以空手走到下一个位置,。
- 如过当前位置有伞,当前位置无雨,Polycarp 可以不拿这把伞空手走到下一个位置,。
- 如过当前位置有伞,Polycarp 拿这把伞,枚举能到达朋友家的点 ,假设在该位置上丢弃伞,。
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <map>
#include <vector>
#include <queue>
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
const int N=2001;
int n,m,len,p;
LL umb[N],dp[N],wgt;
int rain[N];
int main()
{
scanf("%d%d%d",&len,&n,&m);
for (int i=1,x,y;i<=n;++i)
{
scanf("%d%d",&x,&y);
rain[x]++;
rain[y]--;
}
for (int i=1;i<=m;++i)
{
scanf("%d%lld",&p,&wgt);
if (!umb[p]) umb[p]=wgt;
else umb[p]=min(umb[p],wgt);
}
for (int i=1;i<=len;++i) rain[i]+=rain[i-1];
dp[len]=0;
for (int i=len-1;i>=0;--i)
{
if (!umb[i])
{
if (rain[i]) dp[i]=-1;
else dp[i]=dp[i+1];
}
else
{
if (!rain[i]) dp[i]=dp[i+1];
else dp[i]=-1;
for (int j=i+1;j<=len;j++)
if (-1!=dp[j]) dp[i]=min(dp[i]==-1?dp[j]+umb[i]*(j-i):dp[i],dp[j]+umb[i]*(j-i));
}
}
printf("%lld\n",dp[0]);
return 0;
}