美文网首页
POJ3666(Making the Grade)

POJ3666(Making the Grade)

作者: kimoyami | 来源:发表于2018-11-14 19:31 被阅读20次

    链接:https://vjudge.net/problem/POJ-3666
    思路:(本题其实可以只用求递增,数据出的有失误)一直在思考怎么表示状态,猜到了最后结果肯定都是原来的几个数,所以我们可以考虑离散化,考虑到后一位是否要变取决于前一位的最大值,那么我们用dp[i][j]表示枚举到第i个数,且最后一位为第j大的数,转移的话dp[i][j] = min(dp[i-1][1,2,3,....j-1]) +abs(a[i]-c[j]),其实不需要枚举k,用一个变量在递推的时候维护最小值就可以了,好好思考一下离散化+dp的操作。
    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn = 2010;
    ll a[maxn];
    ll c[maxn];
    int n;
    ll dp[maxn][maxn];
    
    int main(){
        while(~scanf("%d",&n)){
            memset(c,0,sizeof(c));
            for(int i=1;i<=n;i++)scanf("%lld",&a[i]),c[i] = a[i];
            memset(dp,0,sizeof(dp));
            sort(c+1,c+n+1);
            int len  = unique(c+1,c+n+1)-c-1;
            for(int i=1;i<=n;i++){
        //递推时维护最小值        
        long long minv = dp[i-1][1];
                for(int j=1;j<=len;j++){
                    minv = min(minv,dp[i-1][j]);
                    dp[i][j] = minv+abs(a[i]-c[j]);
                }
            }
            ll res = 1e18;
            for(int i=1;i<=len;i++)res = min(res,dp[n][i]);
            printf("%lld\n",res);
        }
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:POJ3666(Making the Grade)

          本文链接:https://www.haomeiwen.com/subject/usqsfqtx.html