11282: 【原1282】修路
题目
题目描述
author: Chen Xutong 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1282
Description
蹦蹦跳跳结束后,cxt回头看看自己走过的路坑坑洼洼的,心中非常不爽,他表示要把这段路的路面高度修成单调上升的或者单调下降的,整条路可以看成N段,N个整数A1,…..,An(1<=n<=2000)依次描述了每一段路的高度(0<=Ai<=1000000000)。希望找到一个恰好含N个元素的不上升或不下降的序列B1,……,Bn,作为修过的路中每个路段的高度。
由于将每一段路垫高或挖低一个单位消耗的体力相同,于是可以表示为:
|A1-B1|+|A2-B2|+…..+|An-Bn|
请你计算一下,要修好这段道路,最少消耗多少体力。消耗的总体力不会超过2^31-1
Input Format
输入文件的第一行仅有一正整数N,以下的N行每行一个整数Ai,表示路面的高度。
Output Format
输出文件仅有一个正整数,表示如果把路修成高度不上升或不下降的最小花费
Sample Input
7
1
3
2
4
5
3
9
Sample Output
3
Hint
将第一个高度为3的路段的高度减少为2,将第二个高度为3的路段的高度增加到5,总花费为|2-3|+|5-3|=3,并且各路段的高度为一个不下降序列 1,2,2,4,5,5,9。
ligongzzz's solution
#include "iostream"
#include "cmath"
#include "algorithm"
using namespace std;
int n, ans = 1e9, a[2009], c[2009],
f[2009][2009], g[2009][2009];
void sol()
{
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
{
f[i][j] = g[i - 1][j] + abs(a[i] - c[j]);
if (j == 1)
g[i][j] = f[i][j];
else
g[i][j] = min(f[i][j], g[i][j - 1]);
}
}
for (int i = 1; i <= n; ++i)
ans = min(ans, f[n][i]);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
//输入并排序
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
c[i] = a[i];
}
sort(c + 1, c + n + 1);
sol();
//反序
for (int i = 1; i <= n / 2; ++i)
swap(c[i], c[n - i + 1]);
sol();
cout << ans;
return 0;
}
Neight99's solution
#include <cmath>
#include <iostream>
using namespace std;
const int maxN = 2000 + 100;
long long ans = 1e17, height[maxN] = {0}, height1[maxN] = {0},
dp[maxN][maxN] = {0};
void qSort(long long *, int, int);
void DP(int);
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> height[i];
height1[i] = height[i];
}
qSort(height1, 0, n - 1);
DP(n);
cout << ans;
return 0;
}
void qSort(long long *nums, int l, int h) {
if (l >= h) {
return;
}
int first = l, last = h;
long long key = nums[first];
while (first < last) {
while (first < last && nums[last] >= key) {
--last;
}
nums[first] = nums[last];
while (first < last && nums[first] <= key) {
++first;
}
nums[last] = nums[first];
}
nums[first] = key;
qSort(nums, l, first - 1);
qSort(nums, first + 1, h);
}
void DP(int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == 0) {
if (j == 0) {
dp[i][j] = abs(height1[j] - height[i]);
} else {
dp[i][j] = min(abs(height1[j] - height[i]), dp[i][j - 1]);
}
} else if (j == 0) {
dp[i][j] = dp[i - 1][j] + abs(height1[j] - height[i]);
} else {
dp[i][j] = min(dp[i - 1][j] + abs(height1[j] - height[i]),
dp[i][j - 1]);
}
if (i == n - 1) {
ans = min(ans, dp[i][j]);
}
}
}
for (int i = n - 1; i >= 0; i--) {
for (int j = 0; j < n; j++) {
if (i == n - 1) {
if (j == 0) {
dp[i][j] = abs(height1[j] - height[i]);
} else {
dp[i][j] = min(abs(height1[j] - height[i]), dp[i][j - 1]);
}
} else if (j == 0) {
dp[i][j] = dp[i + 1][j] + abs(height1[j] - height[i]);
} else {
dp[i][j] = min(dp[i + 1][j] + abs(height1[j] - height[i]),
dp[i][j - 1]);
}
if (i == 0) {
ans = min(ans, dp[i][j]);
}
}
}
return;
}
WashSwang's solution
#include <iostream>
#include <cstring>
using namespace std;
int n,h[3000],o[3000];
long long dps[2001][2001],dpt[2001][2001],mins,mint;
void qsort(int *s,int *t){
if (s+1>=t) return;
int i=0,j=int(t-s)-1,x=s[0];
while (i<j){
while (i<j&&s[j]>=x) j--;
if (i<j) s[i++]=s[j];
while (i<j&&s[i]<=x) i++;
if (i<j) s[j--]=s[i];
}
s[i]=x;
qsort(s,s+i);
qsort(s+i+1,t);
}
int main() {
cin>>n;
for (int i=1;i<=n;++i){
cin>>h[i];
o[i]=h[i];
}
qsort(o+1,o+n+1);
for (int i=1;i<=n;++i) {
mins=1e12;
for (int j = 1; j <= n; ++j){
if (dps[i-1][j]<mins) mins=dps[i-1][j];
dps[i][j]=mins+abs(h[i]-o[j]);
}
mint=1e12;
for (int j = n; j>=1;--j){
if (dpt[i-1][j]<mint) mint=dpt[i-1][j];
dpt[i][j]=mint+abs(h[i]-o[j]);
}
}
mins=1e12;
mint=1e12;
for (int i=1;i<=n;++i)
{
mins=min(dps[n][i],mins);
mint=min(dpt[n][i],mint);
}
cout<<min(mins,mint);
return 0;
}