來源:題解
不發題面
因為 l 範圍太大,而石子數卻很少,步數也僅僅在1~10之間,
也就是說兩個石子之間很有可能間隔很大的距離,不管怎麼跳都能跳過去,那麼中間那些怎麼樣都能跳過去的區間和沒有等價,
所以讀入后就更新一遍pos和vis數組,範圍就可以縮到比較小,
至於具體多大的區間可以刪掉,可以取1~10的最小公倍數2520,(小凱的疑惑)71,(t * t-1)90,甚至可以 %t 再 +t,好像都可以
大概是一個離散化的方法吧
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int l,s,t,m,ans; int p[101],d[101],v[300001]; int f[300001]; int main() { scanf("%d%d%d%d",&l,&s,&t,&m); for(int i=1;i<=m;i++){ scanf("%d",&p[i]); } if(s==t){ for(int i=1;i<=m;i++)if(p[i]%t==0)ans++; printf("%d",ans);return 0; } sort(p+1,p+1+m); for(int i=1;i<=m;i++){ d[i]=(p[i]-p[i-1])%2520;//只要兩個石子之間超過1~10的lcm,這一段就相當於沒有,怎麼樣都可以跳過去 } for(int i=1;i<=m;i++){//更新p[i]和v[i] p[i]=p[i-1]+d[i]; v[p[i]]=1; } int l=p[m]; memset(f,0x3f,sizeof(f)); f[0]=0; for(int i=1;i<=l+t;i++)//這裡l+t是因為有可能跳過,預留出跳過頭的範圍,在在區間內找最小值 for(int j=s;j<=t;j++){ if(i-j>=0) f[i]=min(f[i],f[i-j]+v[i]); } int ans=m; for(int i=l;i<l+t;i++)ans=min(ans,f[i]); printf("%d",ans); }