在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:(其中 是桥的长度)。坐标为 的点表示桥的起点,坐标为 的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是 到 之间的任意正整数(包括 )。当青蛙跳到或跳过坐标为 的点时,就算青蛙已经跳出了独木桥。
题目给出独木桥的长度LL,青蛙跳跃的距离范围S,TS,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。
显然是,是用当中的可以做到30分
#include <bits/stdc++.h>//万能头文件
using namespace std;
int l,n,s,t;
map<int,bool>m;//记有没有石头
map<int,int>dp;//最少踩到石头的个数
int main(){
cin>>l>>s>>t>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
m[x]=true;
}
for(int i=1;i<=l+t-1;i++){
dp[i]=INT_MAX/2;
for(int j=s;j<=t&&j<=i;j++)dp[i]=min(dp[i],dp[i-j]);//倒退
if(m[i])dp[i]++;
}int s=dp[l];
for(int i=l+1;i<=l+t-1;i++)s=min(s,dp[i]);
cout<<s;
return 0;
}
之后,我们该想一想如何这道题
我们发现石头数量很少,而独木桥却很长
遇到这张图,我们可能还会选择暴力的方法
但是遇到这张图,你还会用暴力吗?
空的地方就是随便走就行了,完全可以不用老老实实的去看,我们可以把路径压缩,更简单地说就是如果后面的一个石头与前面的一个石头距离太远,我们可以把后面一个石头推到前一个石头附近,至于这个量是多少呢,需要自己把握。
我自己还是觉得稍微保险一点,不要就行了,所以我选择把这个数定在,当然听同学说,他定的比较小也过了,这并没有关系。
所以,我们可以看代码了
#include<bits/stdc++.h>
using namespace std;
int l,s,t,m,a[110],dp[100010],b[110];
bool x[100010];
int main(){
cin>>l;
cin>>s>>t>>m;
for(int i=1;i<=m;i++)cin>>a[i];
sort(a+1,a+1+m);
if(s==t){//这个应该很简单,我上面没有说
int ans=0;
for(int i=1;i<=m;i++)
if(a[i]%s==0)ans++;//如果会经过它,答案+1
cout<<ans;//输出
return 0;
}
for(int i=1;i<=m;i++)
if(a[i]-a[i-1]>1000)b[i]=b[i-1]+1000;//注意啦,如果原来的距离小于1000,你要保持不变
else b[i]=a[i]-a[i-1]+b[i-1];
for(int i=1;i<=m;i++)x[b[i]]=true;//石头
l=b[m];
for(int i=1;i<=l+t-1;i++){
dp[i]=INT_MAX/2;
for(int j=s;j<=t&&j<=i;j++)dp[i]=min(dp[i],dp[i-j]);//转移状态
if(x[i])dp[i]++;
}int ans=dp[l];
for(int i=l;i<=l+t-1;i++)ans=min(ans,dp[i]);//打擂法求最小值
cout<<ans;//输出
return 0;
}