POJ3666 Making the Grade[动态规划]

MakingtheGradeMaking-the-Grade


Description

链接
给出数列AA, 求非严格单调递减或递增, 且 S=i=1NAiBiS = sum_{i=1}^{N}∣A_i-B_i∣ 最小的序列 BB


Solution

BB非严格单调递增为例, 考虑已经选了NN个数, 最小值怎么取

N=1N=1, A1=B1A_1=B_1SS 最小;
N>1N>1时, 假如前面已经选择了N1N-1个数取得了最小值, 考虑怎么取第NN个数
-  当Ai>=Bi1A_i>=B_{i-1}时, Bi=AiB_i=A_i时显然最优.
-  当Ai<Bi1A_i<B_{i-1}时,
     -  使Bi=AiB_i=A_i;
.    -  将Bk,Bk+1...,BiB_k, B_{k+1}..., B_i全部赋值为Ak,Ak+1...,AiA_k, A_{k+1}...,A_i的中位数(根据货仓选址问题显然选择中位数最佳 )

若按照上方直接模拟, 复杂度不可估量(其实是懒得算, 反正过不了)
但是可以得出结论 : BB数列中的每个数必定都为AA数列中的元素

于是可以考虑 dpdp
dpdp到第ii位为阶段, 为了转移, 状态可设dp[i,j]dp[i, j]表示BB的最后一个元素为AjA_j时的SminS_{min},
转移方程: dp[i,j]=max{dp[i1,k]+AiAj}dp[i,j] = max{dp[i-1, k]+∣A_i-A_j∣}Ak<=AjA_k<=A_j
时间复杂度 O(N3)O(N^3)
AA拷贝到CC数组, sortsort排序后保持决策集合增长时新决策的单调性
即可实现O(N2)O(N^2)
具体可以看下方代码


Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define reg register

const int maxn = 2005;

int N;
int A[maxn];
int C[maxn];
int dp[maxn][maxn];

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]), C[i] = A[i];
        std::sort(C+1, C+N+1);
        memset(dp, 0x3f, sizeof dp);
        for(reg int i = 1; i <= N; i ++) dp[0][i] = 0;
        for(reg int i = 1; i <= N; i ++){
                int minn = 0x3f3f3f3f;
                for(reg int j = 1; j <= N; j ++){
                        minn = std::min(minn, dp[i-1][j]);
                        dp[i][j] = std::min(dp[i][j], minn + abs(A[i] - C[j]));
                }
        }
        int Ans = 0x3f3f3f3f;
        for(reg int i = 1; i <= N; i ++) Ans = std::min(Ans, dp[N][i]);
        std::reverse(C+1, C+N+1);
        memset(dp, 0x3f, sizeof dp);
        dp[0][0] = 0;
        for(reg int i = 1; i <= N; i ++){
                int minn = 0x3f3f3f3f;
                for(reg int j = 1; j <= N; j ++){
                        minn = std::min(minn, dp[i-1][j]);
                        dp[i][j] = std::min(dp[i][j], minn + abs(A[i] - C[j]));
                }
        }
        for(reg int i = 1; i <= N; i ++) Ans = std::min(Ans, dp[N][i]);
        printf("%d
", Ans);
        return 0;
}
原文地址:https://www.cnblogs.com/zbr162/p/11822616.html