【BZOJ】1592: [Usaco2008 Feb]Making the Grade 路面修整

【算法】动态规划DP

【题解】

题目要求不严格递增或不严格递减。

首先修改后的数字一定是原来出现过的数字,这样就可以离散化。

f[i][j]表示前i个,第i个修改为第j个数字的最小代价,a表示排序后数组,b表示原数组。

f[i][j]=min(f[i-1][k])+abs(b[i]-a[j])

min部分优化,复杂度O(n^2)。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=2010,inf=0x3f3f3f3f;
int f[maxn][maxn],n,a[maxn],num,b[maxn];
bool cmp(int a,int b){return a>b;}
int abs(int x){return x>0?x:-x;}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
    sort(a+1,a+n+1);
    f[0][0]=0;
    for(int i=1;i<=n;i++){
        num=inf;
        for(int j=1;j<=n;j++){
            num=min(num,f[i-1][j]);
            f[i][j]=num+abs(b[i]-a[j]);
        }
    }
    int ans=inf;
    for(int i=1;i<=n;i++)ans=min(ans,f[n][i]);
    memset(f,0,sizeof(f));
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        num=inf;
        for(int j=1;j<=n;j++){
            num=min(num,f[i-1][j]);
            f[i][j]=num+abs(b[i]-a[j]);
        }
    }
    for(int i=1;i<=n;i++)ans=min(ans,f[n][i]);
    printf("%d",ans);
    return 0;
}
View Code

【CH】整洁的麻将桌差不多。

 

posted @ 2017-08-31 09:27  ONION_CYC  阅读(252)  评论(0编辑  收藏  举报