/*
基础dp
Making the Grade
题意: 给出n个数字组成序列a,然后再找到一个序列b,从1至n,abs(a[i]-b[i])的总和最小,
其中序列b是非严格单调序列,要么是要么是非递减序列,要么是非递增序列。
题解:分别求非严格递减和非严格递减的答案,取最小值
怎么求? 非严格递增:
如果数组数字需要改变,那么往目前数组最大的数字变
将数组排序存于c[];
dp[i][j]代表取第i个数,现在集合最后的数是排序后的数组的第j个
dp[i][j] = min(dp[i-1][k])(1<=k<=j)+abs(a[i]-c[j])
*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2010;
int dp[N];
int n;
int slove(int* now,int* num)
{
memset(dp,0,sizeof(dp));
for(int i = 0; i < n; i++)
{
int mn = INF;
for(int j = 0; j < n; j++)
{
mn = min(mn,dp[j]); //取上个状态 1~j 的最小
dp[j] = mn+abs(now[i]-num[j]);
//printf("%d %d ",num[j],dp[j]);
}
}
int ans = INF;
for(int i = 0; i < n; i++)
ans = min(ans,dp[i]);
return ans;
}
int a[N],b[N],c[N];
int main()
{
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> a[i];
b[n-i-1] = a[i];
c[i] = a[i];
}
sort(c,c+n);
printf("%d\n",min(slove(a,c),slove(b,c)));
return 0;
}
【dp】POJ 3666 Making the Grade
最新推荐文章于 2023-07-23 19:52:14 发布