zoukankan      html  css  js  c++  java
  • POJ 3666(Making the Grade)

    题目链接:http://poj.org/problem?id=3666

    题意:农夫约翰想修一条尽量平缓的路,路的每一段海拔是A_i,修理后是B_i,花费|A_i – B_i|,求最小花费。平缓的意思是海拔单调增或单调减(非严格)

    思路:

    这是一道动态规划的问题,突破口是:每个数最后必然是原序列中的数。

    用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost。

    状态转移方程:dp[i][j]=abs(j-w[i])+min(dp[i-1][k])    (k<=j)

    网上很多都是说用离散化的思想,但是一直不是很理解这是什么意思,就是将序列排序一下,然后用位置的前后关系来制定其值,这样时间复杂度变成O(N^2).

    不是很理解别人的思路,我就想的朴素一点,大概就是把for 循坏 j 的数值的取值范围缩小一些

    ac代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #define MAX_N 2005
    using namespace std;
    typedef long long ll;
    
    ll a[MAX_N],b[MAX_N];
    ll dp[MAX_N][MAX_N];
    int n;
    
    int main(void){	
    	while(~scanf("%d",&n)){
    		memset(a,0,sizeof(a));
    		memset(b,0,sizeof(b));
    		memset(dp,0,sizeof(dp));
    		for(int i=1;i<=n;i++){
    			scanf("%lld",&a[i]);
    			b[i]=a[i];
    		}
    		sort(b+1,b+n+1);
    		
    		for(int i=1;i<=n;i++){
    			ll mn=dp[i-1][1];
    			for(int j=1;j<=n;j++){
    				mn=min(mn,dp[i-1][j]);
    				dp[i][j]=abs(a[i]-b[j])+mn;
    			}
    		}
    		ll ans=dp[n][1];
    		for(int i=2;i<=n;i++)
    			ans=min(ans,dp[n][i]);
    		printf("%lld
    ",ans);	
    	}
    
    	return 0;
    }
    

      

  • 相关阅读:
    Atcoder Grand Contest 003 题解
    Atcoder Grand Contest 002 题解
    Atcoder Grand Contest 001 题解
    网络流24题
    AGC005D ~K Perm Counting
    loj6089 小Y的背包计数问题
    CF932E Team Work
    组合数学相关
    SPOJ REPEATS
    [SDOI2008]Sandy的卡片
  • 原文地址:https://www.cnblogs.com/jaszzz/p/12685454.html
Copyright © 2011-2022 走看看