时间:2016-03-28 17:23:08 星期一
题目编号:[2016-03-28][POJ][3666][]Making the Grade]
分析:dp[i][j]表示把改到第i个数,且把a[i]改成b[i]需要的最少代价,已知b[j]递增,dp[i][j]由dp[i - 1][k]递推过来,如果改成非增,那么就要求 a[j] <= a[k],所以dp[i][j] = min(dp[i - 1][k] + d) k < j;
#include <algorithm>#include <cstring>#include <cstdio>using namespace std;const int maxn = 2000 + 10;int a[maxn],b[maxn],n;int dp[maxn][maxn];bool cmp(int x,int y){ return x > y;}int main(){ scanf("%d",&n); for(int i = 0;i < n ; ++i){ scanf("%d",&a[i]); } memcpy(b,a,sizeof(int) * (n + 1)); sort(b,b + n); memset(dp,0x7f,sizeof(dp)); for(int i = 0;i < n ; ++i){ dp[0][i] = abs(a[0] - b[i]); } for(int i = 1;i < n ; ++i){ int mindp = 0x7f7f7f7f; for(int j = 0;j < n;++j){ mindp = min(dp[i-1][j],mindp); dp[i][j] = min(dp[i][j] , mindp + abs(a[i] - b[j])); } } int ans = 0x7f7f7f7f; for(int i = 0;i < n ; ++i){ ans = min(dp[n - 1][i] ,ans); } sort(b,b + n,cmp); memset(dp,0x7f,sizeof(dp)); for(int i = 0;i < n ; ++i){ dp[0][i] = abs(a[0] - b[i]); } for(int i = 1;i < n ; ++i){ int mindp = 0x7f7f7f7f; for(int j = 0;j < n;++j){ mindp = min(dp[i-1][j],mindp); dp[i][j] = min(dp[i][j] , mindp + abs(a[i] - b[j])); } } for(int i = 0;i < n ; ++i){ ans = min(dp[n - 1][i] ,ans); } printf("%d\n",ans); return 0;}