题意:一个长 的桥,每次可以走
中任意的距离,然后现在有石头在桥上,然后求过桥后不碰到石头的最小次数
题解:dp
通过题目很容易想到
有石头时:
没石头时:
然后呢,这个 的长度
...............所以上面的过不去,然后要进行离散化
离散化:
参考链接:https://www.luogu.com.cn/blog/Actinoi/solution-p1052
#include<bits/stdc++.h>
using namespace std;
const int maxn = 150;
const int maxl = 300 * 105;
//其实开90 * 105就可以了;
int L,s,t,m,stone[maxn],a[maxn],dp[maxl],base;
//stone就是石头的初始位置;a为我们将石头初始化后的石头位置;
bool vis[maxl];
//标记一下坐标上的该点是否为石头;
int main()
{
ios::sync_with_stdio(0);
// 关掉同步,加快cin的速度
cin >> L;
cin >> s >> t >> m;
base = s * t;
for(int i = 1 ; i <= m ; ++ i)
cin >> stone[i];
sort(stone + 1,stone + 1 + m);
// 判段s == t的情况
if(s == t){
int cnt =0;
for(int i = 1 ; i <= m ; ++ i)
if(stone[i] % s == 0)cnt++;
cout << cnt << endl;
return 0;
}
for(int i = 1 ; i <= m ; ++ i)
{
// 离散化过程
int d = stone[i] - stone[i - 1];
if(d >= base)d = base;
a[i] = a[i - 1] + d;
vis[a[i]] = 1;
}
L = a[m] + base;
// 将L变成最后一个石头的位置+s*t
// 如果L - a[m] >= s * t就缩成s * t
// 如果L - a[m] <= s * t就加上一个数使得它等于这个距离因为青蛙可能跳出独木桥
memset(dp,0x7f,sizeof(dp));
dp[0] = 0;
// 初始化到原点寻最少踩0个石头
for(int i = 1 ; i <= L ; ++ i)
for(int j = s ; j <= t ; ++ j)
{
if(i - j >= 0)
{
if(vis[i])dp[i] = min(dp[i - j] + 1,dp[i]);
else dp[i] = min(dp[i - j],dp[i]);
}
}
int ans = maxn;
// 给答案赋一个较大的初值
for(int i = a[m] ; i <= L ; ++ i)
ans = min(ans,dp[i]);
cout << ans << endl;
return 0;
}

京公网安备 11010502036488号