题目描述
在猴村有一条笔直的山路,这条山路很窄,宽度忽略不计。有 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复制
31 4 523 8
输出 #1复制
6
输入 #2复制
33 1 1028 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#include using namespace std;int n,m,i,j; #define ll long long#define INF 46116860184299739803ll 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\n",f[n%2][m]); return 0;}