实际已有的题解已经把大体思路阐述出来了,但我认为缺少很多对细节的解答,故再写了一篇。
题意
大体题意不再阐述,这里有几点需要注意,首先,跳跃后到达的那一格是不算助跑距离的。其次,能跳跃
解析
首先看到数据范围,很容易想到此题是 dp 或者贪心。
然后我们发现,跑道上有若干个障碍,而运动员想要跳跃需要一定的助跑距离,那我们只要让这个助跑距离尽可能大,就更有机会跳过去,因此我们确定这道题的思路为贪心。
我们很容易想到,每次在障碍的前一个单位跳跃,在障碍的后一个单位落下,可以使中间没有障碍的那一段助跑距离尽可能大。当我们这样求出所有障碍之间的最大助跑距离后,仍然有一些障碍之间的助跑距离是不够的,我们可以将这种障碍合在一起,作为一个大障碍考虑。
大体思路如上,但作为一道 CF 的毒瘤题,我们接着还需要通过部分代码来说明几个注意点。
预处理
scanf("%lld%lld%lld%lld",&n,&m,&s,&d); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } sort(a+1,a+1+n); if(a[1]-1<s){ printf("IMPOSSIBLE\n"); return 0; } a[0]=-(1e9+7); for(int i=1;i<=n;i++){ if(a[i]-a[i-1]-1>s) e[++cnt].l=a[i],e[cnt].r=a[i]; else e[cnt].r=a[i]; }
这里有几个非常重要的注意点!一不小心就错了。
首先,我们预处理是从 IMPOSSIBLE
即可。
其次,一定要把
另外别忘了障碍不一定是有序的,需要先排序。
寻找答案
for(int i=1;i<=cnt;i++) if(e[i].r-e[i].l+1>=d){ printf("IMPOSSIBLE\n"); return 0; } int now=0; for(int i=1;i<=cnt;i++){ if(e[i].l!=1){ printf("RUN %lld\n",e[i].l-1-now); printf("JUMP %lld\n",e[i].r+1-(e[i].l-1)); now=e[i].r+1; } } if(now<m) printf("RUN %lld\n",m-now);
这部分相对简单,主要注意当障碍长度等于
代码都在上边呈现了,不再赘述。