Making the Grade---poj3666(类似离散化+dp)
题目链接:http://poj.org/problem?id=3666
题意是给出一组数,每个数代表当前位置的地面高度,问把路径修成非递增或者非递减,需要花费的最小代价?
///用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost。
///dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)
///i-1构成的序列,最大值是k + (j-w[i])变成此步需要的花费
因为要把路径修成非递减路径,所以a[j]>a[k],所以我们要三重循环来搞,时间复杂度O(n^3)。
如果我们对原来数列进行复制排序的话,a[j]>a[k]就转化为了j>k,这样就成功的把时间复杂度从O(n^3)降为O(n^2)。
空间复杂度也可以用滚动数组从O(n^2)变为O(n)。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 2100
#define INF 0x3f3f3f3f
#define met(a) memset(a, 0, sizeof(a))
//1061109567 0x3f3f3f3f
//268435455 0xfffffff 本题用这个会错的;因为它不够大;害的我wa了那么多次-_-;
int n, dp[N][N], a[N], b[N];
int main()
{
while(scanf("%d", &n)!=EOF)
{
met(a); met(b);
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b+1, b+n+1);
for(int i=1; i<=n; i++)
{
int Min = INF;
for(int j=1; j<=n; j++)
{
Min=min(Min, dp[i-1][j]);
dp[i][j] = Min + abs(a[i] - b[j]);
}
}
int ans = INF;
for(int i=1; i<=n; i++)
ans=min(ans, dp[n][i]);
printf("%d\n", ans);
}
return 0;
}

浙公网安备 33010602011771号