码迷,mamicode.com
首页 > 其他好文 > 详细

POJ_3666_Making_the_Grade(动态规划)

时间:2016-04-28 11:48:59      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:

描述


给一串坡的高度,现在要调整某些点,使整个坡单调不降或单调不升.调整的花费为原高度与先高度的差的绝对值,问最小花费(可单增可单降).

 

分析


分单调不增和单调不降两种情况,是一样的,我们分析单调不降的情况.

用dp[i][j]表示前i个点有序且以j结尾的最小花费.则有转移方程:

dp[i][j]=min(dp[i-1][k])+abs(a[i]-j) (0<=k<=j).

但是看数据范围发现高度可以取到10^9,而且分析可知,一个点如果需要调整,为了花费最小,只需要和左边一样就好,所以调整之后的取值一定在a数组中,显然要离散一下.

用dp[i][j]表示前i个点有序且以b[i]结尾的最小花费.则有转移方程:

dp[i][j]=min(dp[i-1][k])+abs(a[i]-a[j])(a[k]<=a[j]).

这样的话就需要三层i,j,k的循环,会超时,考虑把a数组copy一份到b,然后把b升序排列一下,这样在第二层循环里统计k<=j即b[k]<=b[j]的最小的dp[i-1][k].另外,由于只用到了i和i-1,所以可以考虑使用滚动数组.

 

ps.

1.POJ上数据有问题,单调不降一遍就能过,实际上应该dp两遍.

2.感觉自己好弱啊,动规基本都是看题解才做出来的= =,我这样强行作死真的大丈夫?

 

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define for1(i,a,n) for(int i=(a);i<=(n);i++)
#define read(a) a=getnum()
#define CC(i,a) memset(i,a,sizeof(i))
using namespace std;

const int maxn=2000+5,INF=0x7fffffff;
int n;
int a[maxn],b[maxn];
int dp[2][maxn];

inline int getnum()
{
    int r=0,k=1; char c;
    for(c=getchar();c<0||c>9;c=getchar()) if(c==-) k=-1;
    for(;c>=0&&c<=9;c=getchar()) r=r*10+c-0;
    return r*k;
}

bool comp(int a,int b) { return a>b; }

void solve()
{
    sort(b+1,b+n+1);
    for1(i,1,n) dp[1][i]=abs(a[1]-b[i]);
    for1(i,2,n)
    {
        int min_c=dp[(i-1)&1][1];
        for1(j,1,n)
        {
            min_c=min(min_c,dp[(i-1)&1][j]);
            dp[i&1][j]=min_c+abs(a[i]-b[j]);
        }
    }
    int ans=INF;
    for1(i,1,n) ans=min(ans,dp[n&1][i]);
    sort(b+1,b+n+1,comp);
    for1(i,1,n) dp[1][i]=abs(a[1]-b[i]);
    for1(i,2,n)
    {
        int min_c=dp[(i-1)&1][1];
        for1(j,1,n)
        {
            min_c=min(min_c,dp[(i-1)&1][j]);
            dp[i&1][j]=min_c+abs(a[i]-b[j]);
        }
    }
    for1(i,1,n) ans=min(ans,dp[n&1][i]);
    printf("%d\n",ans);
}

void init()
{
    read(n);
    for1(i,1,n)
    {
        read(a[i]);
        b[i]=a[i];
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("making.in","r",stdin);
    freopen("making.out","w",stdout);
#endif
    init();
    solve();
#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    system("making.out");
#endif
    return 0;
}
        
        
        
        

 

POJ_3666_Making_the_Grade(动态规划)

标签:

原文地址:http://www.cnblogs.com/Sunnie69/p/5441813.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!