思路:
- 动态规划+离散化。
- 数据范围过大,需要离散化:A【】是原数组,U【】是去重数组,dp【】是代价。
- 心路历程:
- 最核心的:每改一个数必定不会改成一个在全数组中从未出现过的新数。(dp 依据)
- 令 dp[i][j] 代表前 i 个数符合某规则并且将最后一个元素改成数字 j 所付出的总代价,得到一个 TLE。
- 使用滚动数组,将 dp[maxn][maxn] 改成一维,仍然 TLE。
- 使用变量 PRESUM,降低时间复杂度。
- 注意:
- 两种规则(不升\不降)只需要一次 reverse。
- 用到的STL:unique、reserve、min_element 。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 2005;
int N;
int M;
int ans;
int A[maxn];
int U[maxn];
int dp[maxn][maxn];
int SOLVE(){
for(int i=0;i<M;i++)
dp[0][i] = abs(A[0] - U[i]);
for(int i=1;i<N;i++){
for(int j=0;j<M;j++){
int MIN = INF;
for(int k=0;k<=j;k++)
MIN = min(MIN , dp[i-1][k]);
dp[i][j] = MIN + abs(A[i] - U[j]);
}
}
return *min_element(dp[N-1] , dp[N-1] + M);
}
int main(){
cin>>N;
for(int i=0;i<N;i++)
cin>>A[i] , U[i] = A[i];
sort(U , U + N);
M = unique(U , U + N) - U;
ans = INF;
ans = min(ans , SOLVE());
reverse(U , U + N);
ans = min(ans , SOLVE());
cout<<ans<<endl;
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 2005;
int N;
int M;
int ans;
int A[maxn];
int U[maxn];
int dp[maxn];
int SOLVE(){
memset(dp , 0 , sizeof(dp));
for(int i=0;i<N;i++){
for(int j=M-1;j>=0;j--){
int MIN = INF;
for(int k=0;k<=j;k++)
MIN = min(MIN , dp[k]);
dp[j] = MIN + abs(A[i] - U[j]);
}
}
return *min_element(dp , dp + M);
}
int main(){
cin>>N;
for(int i=0;i<N;i++)
cin>>A[i] , U[i] = A[i];
sort(U , U + N);
M = unique(U , U + N) - U;
ans = INF;
ans = min(ans , SOLVE());
reverse(U , U + N);
ans = min(ans , SOLVE());
cout<<ans<<endl;
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 2005;
int N;
int M;
int ans;
int A[maxn];
int U[maxn];
int dp[maxn];
int SOLVE(){
memset(dp , 0 , sizeof(dp));
for(int i=0;i<N;i++){
int PRESUM = INF;
for(int j=0;j<M;j++){
PRESUM = min(PRESUM , dp[j]);
dp[j] = PRESUM + abs(A[i] - U[j]);
}
}
return *min_element(dp , dp + M);
}
int main(){
cin>>N;
for(int i=0;i<N;i++)
cin>>A[i] , U[i] = A[i];
sort(U , U + N);
M = unique(U , U + N) - U;
ans = INF;
ans = min(ans , SOLVE());
reverse(U , U + N);
ans = min(ans , SOLVE());
cout<<ans<<endl;
return 0;
}