[P2769] 猴子上樹

題目描述

在猴村有一條筆直的山路,這條山路很窄,寬度忽略不計。有 n只猴子正站在山路上靜靜地觀望今天來參加比賽的各位同窗。用一個正整數Xi表示第i只猴子所站位置,任意兩隻猴子的所站位置互不相同。在這條山路的m個位置上種着一些高大的樹木,正整數Yj表示第j棵樹木所在的位置,任意兩棵樹的位置互不相同。ios

正當猴子們聚精會神的欣賞各位高超編程技能 聚精會神的欣賞各位高超編程技能時,一隻老虎大搖擺的走了過來。猴子們嚇得直冒冷汗,第一反應就是找棵大樹爬上去這樣能避免被老虎咬死或者吃掉(不考慮老虎上樹問題)。編程

在位置a的猴子跑到在位置b的大樹上,須要消耗能量爲|a-b|(即 a-b的絕對值)。爲了儘量有效利用這些大樹避難,每棵上至少要一隻猴子。 請編程計算n只猴子所有上樹最少須要消耗多能量?數組

輸入輸出格式

輸入格式:優化

輸入共4行。spa

第1行一個整數 n,表示猴子的數量。code

第2行n個整數,i個整數個整數Xi表示第i只猴子所在的位置。blog

第3行一個整數m,表示大樹的數量。排序

第4行m個整數,第j個整數表示第j棵大樹所在的位置。ci

輸出格式:get

輸出一行,一個整數表示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≤X_i,Y_i≤10^5\)

100%的數據,\(1≤n≤5000,1≤m≤n,1≤Xi_,Y_i≤10^9\)

Solution

動態規劃+滾動數組優化空間+排序。
先把猴子和樹排序,這很容易想到,貪心確定不行,由於你沒法肯定哪些樹有猴子,並且保證全局最優,因而想到了DP。
咱們設\(f[i][j]\)表明前\(i\)只猴子佔滿了前\(j\)顆樹,容易想到DP方程爲
\[f[i][j]=min(f[i-1][j-1]+abs(x[i]-y[j]),f[i-1][j]+mn[i][j]);\]
\(mn[i][j]\)表明第\(i\)只猴子在上前\(j\)顆樹的最小能量,能夠預處理出來。
發現\(f[i][j]會爆\)\(int\),因此要開\(long~long\),數據範圍5000?,好像
\(f[5000][5000]\)會爆,容易發現\(f[i][j]\)轉移只和上一次有關,能夠用滾動數組,因而轉移方程爲\[f[p][j]=min(f[p~xor~1][j-1]+abs(x[i]-y[j]),f[p~xor~1][j]+mn[i][j]);\]
代碼以下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll f[2][5010],x[10010],y[10010];
int mn[5010][5010];
int sba(int x)
{
    if(x<0) return -x;
    return x;
}
int main()
{
    memset(f,0x3f,sizeof(f));
    ll n,m;
    cin>>n;
    for(ll i=1;i<=n;i++)
    cin>>x[i];
    sort(x+1,x+1+n);
    cin>>m;
    for(ll i=1;i<=m;i++)
    cin>>y[i];
    sort(y+1,y+1+m);
    for(ll i=1;i<=n;i++)
    mn[i][0]=2e9;
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=m;j++)
    mn[i][j]=min(mn[i][j-1],sba(x[i]-y[j]));
    f[1][1]=sba(x[1]-y[1]);
    for(ll i=2;i<=n;i++)
    {
        ll qq=min(i,m);
        for(ll j=1;j<=qq;j++)
        {
            ll p=i%2;
            f[p][j]=min(f[p^1][j-1]+sba(x[i]-y[j]),f[p^1][j]+mn[i][j]);
        }
    }
    ll p=n%2;
    cout<<f[p][m];
}

博主蒟蒻,能夠隨意轉載,但必須附上原文連接k-z-j

相關文章
相關標籤/搜索