P1052 过河(离散化+dp)
dp不难,重点是要想到离散化。
石子个数$<=100$意味着有大量空间空置,我们可以缩掉这些空间。
实现的话自己yy下就差不多了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define re register using namespace std; int max(int &a,int &b){return a>b?a:b;} int min(int &a,int &b){return a<b?a:b;} int s,t,m,l,f[10000],a[102],b[10000]; int main(){ scanf("%d%d%d%d",&l,&s,&t,&m); for(int i=1;i<=m;++i) scanf("%d",&a[i]); sort(a+1,a+m+1); int pre=0,z,d=l-a[m],tmp; //d:最后一个石子与终点的距离 for(int i=1;i<=m;++i){ if(a[i]-pre>=2*t){ tmp=(a[i]-pre)%t; pre=a[i]; a[i]=a[i-1]+tmp+t; }else z=a[i],a[i]=a[i-1]+a[i]-pre,pre=z; }//缩空间 tmp=d/t-1; d-=tmp*t; l=a[m]+d; for(int i=1;i<=m;++i) b[a[i]]=1;//有石子的地方 memset(f,127,sizeof(f)); f[0]=0; for(int i=1;i<=l+t;++i) for(int j=max(0,i-t);j<=i-s;++j) f[i]=min(f[i],f[j]+b[i]); int ans=1e9; for(int i=l;i<=l+t;++i) ans=min(ans,f[i]);//注意可以超出终点,这意味着答案是一个范围。 printf("%d",ans); return 0; }