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棵树的消耗的最小能量。
对于转移方程:如果j==1,即只有一棵树,那么f[i][j]必然等于f[i-1][j]+abs(a[i]-b[j])
如果j==i,即i只猴子上i棵树,又因为每棵树上必有一致猴子,f[i][i]必然等于f[i-1][i-1]+abs(a[i]-b[i])

#include<cstdio>
#include<algorithm>
using namespace std;

int n,m,i,j; 

#define ll long long
#define INF 46116860184299739803

ll mon[5005];
ll tree[5005];
ll f[2][5005];
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-'){
            w=-1;
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*w;
}


int main(){
    n=read();
    for(i=1;i<=n;i++){
        mon[i]=read();
    }
    m=read();
    for(i=1;i<=m;i++){
        tree[i]=read();
    }
    sort(mon+1,mon+n+1);
    sort(tree+1,tree+m+1);
    f[1][1]=abs(mon[1]-tree[1]);
    for(i=2;i<=n;i++){
        for(j=1;j<=m;j++){
            if(j==1){
                f[i%2][1]=f[(i-1)%2][1]+abs(mon[i]-tree[j]);
                continue;
            }
            if(i==j){
                f[i%2][j]=f[(i-1)%2][j-1]+abs(mon[i]-tree[j]);
                break;
            }
            f[i%2][j]=min(f[(i-1)%2][j],f[(i-1)%2][j-1])+abs(mon[i]-tree[j]);
        }
    }
    printf("%lld
",f[n%2][m]);
    return 0;
}
原文地址:https://www.cnblogs.com/hrj1/p/11538055.html