洛谷p2769猴子上树题解

题目描述

在猴村有一条笔直的山路,这条山路很窄,宽度忽略不计。有 n 只猴子正站在山路上静静地观望今天来参加比赛的各位同学。用一个正整数 Xi​ 表示第 i 只猴子所站位置,任意两只猴子的所站位置互不相同。在这条山路的 m 个位置上种着一些高大的树木,正整数 Yj​ 表示第 j 棵树木所在的位置,任意两棵树的位置互不相同。

正当猴子们聚精会神的欣赏各位高超编程技能 聚精会神的欣赏各位高超编程技能时,一只老虎大摇摆的走了过来。猴子们吓得直冒冷汗,第一反应就是找棵大树爬上去这样能避免被老虎咬死或者吃掉(不考虑老虎上树问题)。

在位置 a 的猴子跑到在位置 b 的大树上,需要消耗能量为 ∣a−b∣(即 a−b 的绝对值)。为了尽可能有效利用这些大树避难,每棵上至少要一只猴子。 请编程计算 n 只猴子全部上树最少需要消耗多少能量?

输入格式

输入共 4 行。

第 1 行一个整数 n,表示猴子的数量。

第 2 行 n 个整数,第 i 个整数 Xi​ 表示第 i 只猴子所在的位置。

第 3 行一个整数 m,表示大树的数量。

第 4 行 m 个整数,第 j 个整数表示第 j 棵大树所在的位置。

输出格式

输出一行,一个整数表示 n 只猴子全部上树最少需要消耗的能量。

输入输出样例

输入 #1复制

3
1 4 5
2
3 8

输出 #1复制

6

输入 #2复制

3
3 1 10
2
8 3

输出 #2复制

4

说明/提示

30% 的数据,1≤n≤500,1≤Xi,Yi≤10^5。

100% 的数据,1≤n≤5000,1≤m≤n,1≤Xi,Yi≤10^9。

思路:

考虑动态规划。

设 f [ i ][ j ] 为前 i 只猴子上前 j 棵树花费的最小能量。

第 i 只猴子要么共享第 j 棵树,要么独占第 j 棵树。

所以有 f [ i ][ j ] = min ( f [ i - 1][ j ],f [ i - 1][ j - 1] ) + 距离之差 。

提交代码。

咦?MLE了?

改成滚动数组

咦?WA了?

改long long

十年oi一场空

不开long long见祖宗

AC了

Code:

#include<bits/stdc++.h>
using namespace std;
long long n,mo[5005],tree[5005],m,f[2][5005],i=1,j=1;
int main(){
    cin>>n;
    for(i=1;i<=n;i++)cin>>mo[i];
    cin>>m;
    for(i=1;i<=m;i++)cin>>tree[i];
    sort(mo+1,mo+n+1);
    sort(tree+1,tree+m+1);
    memset(f,0x7f,sizeof(f));
    f[1][1]=abs(mo[1]-tree[1]);
    for(i=2;i<=n;i++)
        for(j=1;j<=m;j++)
      	    f[i%2][j]=min(f[(i-1)%2][j],f[(i-1)%2][j-1])+abs(mo[i]-tree[j]);
    cout<<f[n%2][m];
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
过河卒是一个典型的动态规划问题。首先,我们将整个棋盘看作一个二维数组,数组的每个元素表示到达该位置的路径数目。然后,我们根据题目给出的条件,逐步更新数组中的元素,直到计算出到达目标位置的路径数目。 具体的解题思路如下: 1. 首先,我们可以将马的位置设置为0,表示无法经过该位置。 2. 然后,我们根据马的位置,更新数组中的元素。对于二维数组中的每个位置,我们根据左边和上边的位置来计算到达当前位置的路径数目。具体地,如果左边和上边的位置都可以经过,那么到达当前位置的路径数目就等于左边和上边位置的路径数目之和。如果左边或上边的位置无法经过,那么到达当前位置的路径数目就等于左边或上边位置的路径数目。 3. 最后,我们输出目标位置的路径数目。 下面是洛谷p1002过河卒题解C++代码: ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long a[21][21]; int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; // 初始化数组,马的位置设置为0 for(int i=0; i<=20; i++) { for(int k=0; k<=20; k++) { a[i][k] = 1; } } a[x2][y2] = 0; // 根据马的位置更新数组中的元素 if(x2 >= 2 && y2 >= 1) a[x2-2][y2-1] = 0; if(x2 >= 1 && y2 >= 2) a[x2-1][y2-2] = 0; if(x2 <= 18 && y2 >= 1) a[x2+2][y2-1] = 0; if(x2 <= 19 && y2 >= 2) a[x2+1][y2-2] = 0; if(x2 >= 2) a[x2-2][y2+1] = 0; if(x2 >= 1) a[x2-1][y2+2] = 0; if(y2 >= 1) a[x2+2][y2-1] = 0; if(y2 >= 2) a[x2+1][y2-2] = 0; // 动态规划计算路径数目 for(int i=1; i<=20; i++) { for(int k=1; k<=20; k++) { if(a[i][k] != 0) { a[i][k] = a[i-1][k] + a[i][k-1]; } } } // 输出目标位置的路径数目 cout << a[x1][y1] << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值