zoukankan      html  css  js  c++  java
  • 【DP合集】合并 union

    给出一个 1 ∼ N 的序列 A ( A 1 , A 2 , ..., A N ) 。你每次可以将两个相邻的元素合并,合并后的元素权值即为 这两个元素的权值之和。求将 A 变为一个非降序列,最少需要多少步操作。

    Input

    输入的第一行一个整数 N ( N ≤ 5000) 。 
    接下来一行 N 个整数,描述序列 A 。保证序列 A 中的每个元素的值不超过 1000 。

    Output

    输出一行一个整数,表示最少的操作数。

     
    题解:
    区间dp真的难,(。・∀・)ノ゙嗨!
    好了,设dp[i][j]表示从区间把前j个数,把区间i~j合并后满足单调的元素数量,我们可以考虑,统计一个前缀和sum,然后枚举
    三个端点i,j,k,我们是想把i~j压缩成一个数,然后k在i之前,找到元素数量最少的,进行转移,转移条件 是sum[i]-sum[k-1]<=sum[j]-sum[i]
    代码:
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<cstring>
    const int MAXN=5100; 
    using namespace std;
    int dp[MAXN][MAXN],sum[MAXN],ans=-1;
     
    void cl(){
        memset(dp,0,sizeof(dp));
        memset(sum,0,sizeof(sum));
    }
     
    int main(){
        cl();
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&sum[i]);
            sum[i]+=sum[i-1];
        }
        for(int i=1;i<=n;i++){
            dp[i][1]=1;
            int k=i,res=-1;
            for(int j=i+1;j<=n;j++){
                while(k&&sum[i]-sum[k-1]<=sum[j]-sum[i]) res=max(res,dp[i][k--]);
                if(res==-1) dp[j][i+1]=-1;
                else dp[j][i+1]=max(dp[j][i+1],res+1);
                //printf("i=%d j=%d k=%d
    ",i,j,k); 
            }
        }
        for(int i=1;i<=n;i++) ans=max(ans,dp[n][i]);
        if(ans==-1) printf("-1");
        else printf("%d",n-ans);
    }
  • 相关阅读:
    leetcode1046
    leetcode1041
    leetcode1042
    leetcode399
    【经验分享】数据科学与机器学习面试指南
    计算机视觉计算任务有哪些,怎么分类 ?
    超详细!上线一个机器学习项目你需要哪些准备?
    人工智能和机器学习的前世今生
    机器学习从业人员到底做什么?
    两年AI研究经验(教训)总结,进来看看吧!
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7192505.html
Copyright © 2011-2022 走看看