浅谈做题做程
刚开始一看还以为是一道数学题,于是便开始睿智地打了试着调了一下。不出意外,写挂了。但是仔细看了之后,通过题意,可以发现此题其实是一道dp题
分析
通过推理,我们可以得知以下购买最为划算的三点。
ps:我用变量m
来指时间。
- 当 m ≥ 1440 m \ge 1440 m≥1440 时,选择花 120 120 120 元来购买 1440 m i n 1440min 1440min 的票最为划算。
- 当 m ≤ 90 m \le 90 m≤90 时,选择花 50 50 50 元来购买 90 m i n 90min 90min 的票最为划算。
- 最后都不行的话,购买 20 20 20 元的单程票。
做法
首先初始化 d p [ 0 ] = 0 dp[0] = 0 dp[0]=0
然后就有三种转移方式
- 购买单程票时, d p [ i ] = d p [ i − 1 ] + 20 dp[i] = dp[i - 1] + 20 dp[i]=dp[i−1]+20
- 购买 90 m i n 90min 90min 的票时, d p [ i ] = d p [ x − 1 ] + 50 dp[i] = dp[x - 1] + 50 dp[i]=dp[x−1]+50, x x x 为 90 m i n 90min 90min 以内最早的上个车次。
- 购买 1440 m i n 1440min 1440min 的票时, d p [ i ] = d p [ y − 1 ] + 120 dp[i] = dp[y - 1] + 120 dp[i]=dp[y−1]+120, y y y 为 1440 m i n 1440min 1440min 以内最早的上个车次。
最后再求出第 i i i 次与第 i − 1 i - 1 i−1 次的花费最小值。
在求
x
x
x 和
y
y
y 的值时,我们可以使用lower_bound
函数,进行查找第一个大于等于
a
[
i
]
−
90
+
1
a[i] - 90 + 1
a[i]−90+1 或
a
[
i
]
−
1440
+
1
a[i] - 1440 + 1
a[i]−1440+1 的数字的下标。
AC code
/*
CF756B Travel Card
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n;
int a[maxn],dp[maxn];
int main()
{
cin>>n;
for(int i = 1;i <= n;i++)
{
cin>>a[i];
}
dp[0] = 0;//初始化
for(int i = 1;i <= n;i++)
{
int x = lower_bound(a + 1,a + i + 1,a[i] - 90 + 1) - a;//查找第一种
int y = lower_bound(a + 1,a + i + 1,a[i] - 1440 + 1) - a;//查找第二种
int aa = dp[x - 1] + 50;//第一种求值
int bb = dp[y - 1] + 120;//第二种求值
int z = dp[i - 1] + 20;//查找并求值第三种
dp[i] = min(z,min(aa,bb));//求三种的最小值
}
for(int i = 1;i <= n;i++)
{
cout<<dp[i] - dp[i - 1]<<endl;//计算输出
}
return 0;
}