POJ 3666 dp

题意

传送门 POJ 3666

基本思路是对 N 个位置枚举所有可能高度,并 dp 求最大值。可能高度取 N 个位置的高度即可,排序以方便顺序 dp。对于升序的情况

d p [ i ] [ j ] = m a x { d p [ i 1 ] [ j ] } + a b s ( B [ j ] A [ i ] ) , j j dp[i][j]=max\{dp[i-1][j']\}+abs(B[j]-A[i]),j'\leq j

复杂度为 O ( n 3 ) O(n^3) ,递推式可以优化为 O ( n 2 ) O(n^2)

d p [ i ] [ j ] = m a x { d p [ i 1 ] [ j ] , d p [ i ] [ j 1 ] a b s ( B [ j 1 ] A [ i ] ) } + a b s ( B [ j ] A [ i ] ) dp[i][j]=max\{dp[i-1][j],dp[i][j-1]-abs(B[j-1]-A[i])\}+abs(B[j]-A[i])

实现上复用数组,降序情况同理。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-3
#define PI 3.14159265358979323846
#define MAX_N 2010
using namespace std;
int N;
int A[MAX_N], B[MAX_N], dp[MAX_N];

int main(){
	while(~scanf("%d", &N)){
		for(int i = 0; i < N; i++){
			scanf("%d", A + i);
			B[i] = A[i];
		}
		sort(B, B + N);
		int res = INF;
		// 升序 dp
		for(int i = 0; i < N; i++) dp[i] = abs(A[0] - B[i]);
		for(int i = 1; i < N; i++){
			dp[0] += abs(A[i] - B[0]);
			for(int j = 1; j < N; j++){
				dp[j] = min(dp[j], dp[j - 1] - abs(A[i] - B[j - 1])) + abs(A[i] - B[j]);
			}
		}
		for(int i = 0; i < N; i++) res = min(res, dp[i]);
		// 降序 dp
		for(int i = 0; i < N; i++) dp[i] = abs(A[0] - B[i]);
		for(int i = 1; i < N; i++){
			dp[N - 1] += abs(A[i] - B[N - 1]);
			for(int j = N - 2; j >= 0; j--){
				dp[j] = min(dp[j], dp[j + 1] - abs(A[i] - B[j + 1])) + abs(A[i] - B[j]);
			}
		}
		for(int i = 0; i < N; i++) res = min(res, dp[i]);
		printf("%d\n", res);
	}
	return 0;
}
发布了91 篇原创文章 · 获赞 1 · 访问量 1619

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/105127771