題解:本題主要考查dp+路徑壓縮。
簡要題意:有一條米長的橋,橋上有個石頭。小青蛙從橋頭開始,向終點跳。跳躍距離爲到,求青蛙最少需要踩到的石子數。
1.dp:本題的難點不在dp的轉移方程上,易得出:設爲在上經過的石頭數
位置上有石頭:
位置上無石頭:
2.路徑壓縮:本題的規模極大,但很小,所以就需要巧妙的路徑壓縮。我們發現以後的每個點都可以到達, 所以我們只需將每兩個石頭超過的距離縮成就可以了
代碼如下:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int stone[233333],v[999999],f[233333],a[233333];
int n,s,t,m,ans=0x3f3f3f,d;
int main()
{
cin>>n>>s>>t>>m;
for(int i=1;i<=m;i++)cin>>stone[i];
sort(stone+1,stone+m+1);
if(s==t)
{
int sum=0;
for(int i=1;i<=m;i++)
if(stone[i]%s==0)sum++;
cout<<sum<<endl;cin>>n;
return 0;
}
for(int i=1;i<=m;i++)
{
d=stone[i]-stone[i-1];
if(d>s*t)d=s*t;
a[i]=a[i-1]+d;
v[a[i]]=1;
}
if(a[m]+s*t<n)
n=a[m]+s*t;
memset(f,0x3f3f3f,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++)
for(int j=s;j<=t;j++)
if(i>=j)
{
if(v[i]==1)f[i]=min(f[i],f[i-j]+1);
else f[i]=min(f[i],f[i-j]);
}
for(int i=1;i<=n;i++)
ans=min(ans,f[n]);
cout<<ans<<endl;
return 0;
}