【NOIP2005】过河

感觉这题好玄……最后看了chty的代码才过,我现在这样必须看题解才能A题怎么办嘛qaq

原题:

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

  题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

L <= 10^9。

 

离散化,打表发现如果从1开始的话到第(s-1)*(t-1)之后就一定能达到了,所以如果这个点和上一个点距离差大于(s-1)*(t-1),这个点的坐标就是上一个点的坐标加上坐标差%(s-1)*(t-1)

然后根据新坐标dp即可,f[i]=min(f[i],f[i-j]+flag[i])(s<=j<=t),flag表示i是不是石子

有一个很坑的地方,如果s==t要特判,如果石子的坐标%t==0,ans++,不知道为什么

感觉好晕qaq

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int l,s,t,m,a[110];
 8 int tl=0;
 9 int f[1100000];
10 bool is[1100000];
11 int main(){freopen("ddd.in","r",stdin);
12     memset(f,10,sizeof(f));
13     memset(is,0,sizeof(is));
14     cin>>l>>s>>t>>m;
15     for(int i=1;i<=m;i++)  scanf("%d",&a[i]);
16     sort(a+1,a+m+1);  a[m+1]=l;
17     if(s==t){
18         int ans=0;
19         for(int i=1;i<=m;i++)  if(!(a[i]%s))  ans++;
20         cout<<ans<<endl;
21         return 0;
22     }
23     for(int i=0;i<=m;i++)
24         if(a[i+1]-a[i]>(s-1)*(t-1))  a[i+1]=a[i]+(a[i+1]-a[i])%((s-1)*(t-1));
25     for(int i=1;i<=m;i++)  is[a[i]]=true;
26     f[0]=0;
27     for(int i=s;i<=t;i++)  f[i]=is[i];
28     for(int i=s*2;i<=a[m+1];i++){
29         for(int j=s;j<=t && i>=j;j++)
30             f[i]=min(f[i],f[i-j]);
31         f[i]+=is[i];
32     }
33     cout<<f[a[m+1]]<<endl;
34     return 0;
35 }
View Code

 

转载于:https://www.cnblogs.com/JSL2018/p/5946642.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值