2 条题解

  • 1
    @ 2022-10-23 21:17:31

    在题解开始之前,先让我%%%%%一下@尚轩好大神,相比孙老板的dp,他的代码更加容易理解(也更好码)


    那么首先让我们来读一下题 有两只青蛙A,B,他们都要跳过n个石子。石子间的距离有长有短,有些甚至超过了青蛙们的弹跳能力,怎么办呢?他们有一个超级大宝贝

    助跳器

    这个助跳器非常强大,可以让青蛙的弹跳能力由m变为k。而根据题中数据保证,有了助跳器的青蛙可以一路跳到终点! 那么该怎么决定青蛙拿到弹跳器的顺序呢?


    先看看题目的样例说明

    青蛙 𝐴 先走到第二颗石头(位置 10),此时将助跳器传递给青蛙 𝐵;青蛙 𝐵 跳 到终点(位置 20)再将助跳器传递给 𝐴,𝐴 跳到终点。

    注意:若 𝐴 直接跳到终点,则此时助跳器传递不到 𝐵(因为两青蛙此时的距离 大于 𝑞), 𝐵 无法抵达终点。

    明显的,如果我们一开始先让a跳,是非常难以考虑的。代码的执行有先后,如果你不知道b在没有助跳器的情况下能跳到什么位置,那你也决定不了a要跳到哪个位置(a需要给b助跳器,条件是a与b距离小于q) 所以,我们要反其道而行之,先让b跳到他的极限 这个代码实现非常简单,如果下一块石头和他脚踩的距离小于m就跳过去,就不贴出来了; b跳完了,那么现在看看a 对于持有助跳器的a来说,他想跳到哪里就跳哪里,重要的是他需要给b助跳器,明显的,他所能跳到的最远距离是和b相差小于等于q的距离。我们把他跳过去,就让他把助跳器给过去。 此时拿有助跳器的b,操作上是可以等同a的,他也可以跳到任意位置,重要的是失去助跳器后的a能跳到哪个位置

    那么讲到这里,其实大家应该也差不多懂了吧,下面是核心代码;


    void bs()
    {
    	while(y<n&&b[y+1]-b[y]<=m)
    		y++;
    	if(y==n)return ;
    	while(x<n&&a[x+1]-b[y]<=q)
    		x++;
    	ans++;
    	as();
    }
    

    最后%%%%一下葛雨墨大神,上能codding,下能文能理,在考试中取得nb的成绩。

    • 0
      @ 2022-10-23 21:21:46

      孙老板的代码 (dp),能看懂就看看吧 ,没准以后可能大概也许或许会来注释

      #include <bits/stdc++.h>
      using namespace std;
      const int maxn = 1005;
      int a[maxn], b[maxn], dp[maxn][maxn][2];
      int main(){
      	//freopen("pass.in","r",stdin);
      	//freopen("pass.out","w",stdout);
      	int n, m, k, q;
      	cin >> n >> m >> k >> q;
      	for(int i = 1; i <= n; i++){
      		cin >> a[i];
      	}
      	for(int i = 1; i <= n; i++){
      		cin >> b[i];
      	}
      	a[n+1] = a[n];
      	b[n+1] = b[n];
      	memset(dp, 0x3f, sizeof dp);
      	dp[0][0][0] = 0;
      	dp[0][0][1] = 1;
      	for(int step = 0; step <= 2 * n; step++){
      		for(int j = 0; j <= min(n, step); j++){
      			int i = step - j;
      			if(i > n)	continue;
      			for(int k = 0, r = 0; r <= 3; k++, r++){ // 枚举第三维时,在原地转移 4 次,这样 0 1 都被互相求 min
      				k = r % 2;
      				if(dp[i][j][k] >= 1e9)	continue;
      				if(abs(a[i] - b[j]) <= q)
      					dp[i][j][k^1] = min(dp[i][j][k^1], dp[i][j][k] + 1);
      				if(k == 0){
      					dp[i+1][j][k] = min(dp[i+1][j][k], dp[i][j][k]);
      					if(b[j+1] - b[j] <= m){
      						dp[i][j+1][k] = min(dp[i][j+1][k], dp[i][j][k]);
      					}
      				}else{
      					dp[i][j+1][k] = min(dp[i][j+1][k], dp[i][j][k]);
      					if(a[i+1] - a[i] <= m){
      						dp[i+1][j][k] = min(dp[i+1][j][k], dp[i][j][k]);
      					}
      				}
      			}
      		}
      		
      	}
      	cout << min(dp[n][n][0], dp[n][n][1])<< endl;
      	return 0;
      }
      
      • 1

      信息

      ID
      785
      时间
      1000ms
      内存
      256MiB
      难度
      7
      标签
      (无)
      递交数
      35
      已通过
      8
      上传者