这个题非常的坑、、只能想到nT做法、感觉中途肯定有很多费步、而且石子非常少,可以想到围绕石子走、但石子前的必须递推来、
好吧,其实这个题,只需要对每个位置判断,没有必要每条路走下去、、就是说你只需要看这个点可不可以被前面的所有点更新到即可,
即对于s到t这些数 从原点开始 找到一个距离范围(大于等于某个值),使这个范围内所有的数都可以被原点以左的点 +几个(s到t之间的数) 得到、
设这个范围为p,则>p的和=p的都是被全部原点以左的数转移、显然=p的步数最少、
例如对于s=3,t=5;
这个限度很显然是 s*(s-1) 因为对于小于s*(s-1)的数,它不能由最小的s补起来
但如果是s==t 那这个坑是永远填不上的、因为只有一个数,肯定有空隙
码:
#include<iostream> #include<cstdio> using namespace std; #include<algorithm> #include<cstring> int l,s,t,n,i,a[100005],f[100005],ans,b[100005],j; bool lei[100005]; int main() { scanf("%d%d%d%d",&l,&s,&t,&n); for(i=1;i<=n;i++)scanf("%d",&a[i]); if(s==t) { for(i=1;i<=n;i++)if(!(a[i]%s))++ans; cout<<ans; return 0; } sort(a+1,a+1+n); if(a[1]>100)b[1]=100; else b[1]=a[1]; for(i=2;i<=n;i++) if(a[i]>a[i-1]+100)b[i]=b[i-1]+100; else b[i]=b[i-1]+(a[i]-a[i-1]); for(i=1;i<=n;i++)lei[b[i]]=1; ans=1e8; l=b[n]+t; memset(f,0x7f,sizeof(f)); f[0]=0; for(i=s;i<=l;i++) { for(j=s;j<=t;j++) { if(i-j<0)break; f[i]=min(f[i],f[i-j]); } if(lei[i])f[i]+=1; } for(i=b[n];i<=l;i++) ans=min(ans,f[i]); cout<<ans; }
