dpdp.cpp

0.爬楼梯:

    int n;
    ::scanf("%d",&n);
    int dp[n];
    dp[0]=1;
    dp[1]=2;
    for (int i = 2; i < n; ++i) {
        dp[i]=dp[i-1]+dp[i-2];
    }
    ::printf("%d",dp[n-1]);

1.最大子列和:

int n;
    ::scanf("%d",&n);
    int arr_text[n];
    for (int i = 0; i < n; ++i) {
        ::scanf("%d",&arr_text[i]);
    }

    int dp[n];
    dp[0]=arr_text[0];
    int res=dp[0];
    for (int i = 1; i < n; ++i) {
        dp[i]= max(dp[i-1]+arr_text[i],arr_text[i]);
        res= max(res,dp[i]);
    }
    ::printf("%d",res);

用res记录最大;


2.三角数:

    ::scanf("%d",&n);
    for (int i = 1; i < n+1; ++i) {
        for (int j = 1; j < 1+i; ++j) {
            ::scanf("%d",&a[i][j]);
        }
    }


    dp[1][1]=a[1][1];
    int res=dp[1][1];
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            dp[i][j]= max(dp[i-1][j-1]+a[i][j],dp[i-1][j]+a[i][j]);

        }
    }
    for (int i = 1; i <= n; ++i) {
        res= max(res,dp[n][i]);
    }


    ::printf("%d",res);
    return 0;

迭代,在最后一行找最大


摆花:

    int n,m;
    int mod=1000007;
    int f[110][110];//i种花,摆j盆

    ::scanf("%d %d",&n,&m);
    int a[n];
    for (int i = 1; i <= n; ++i) {
        ::scanf("%d",&a[i]);
    }

    for (int i = 1; i < n; ++i) {
        f[i][0]=1; // j=0可摆放0;那么只有1种情况
    }
    for (int i = 0; i <= a[1]; ++i) {
        f[1][i]=1; // i=1一种花;只有一种情况:摆到a[i]
    }

    for (int i = 2; i <=n ; ++i) {
        for (int j = 1; j <= m; ++j) {
            for (int k = 0; k <= a[i]&&k<=j; ++k) {
                f[i][j]=(f[i][j]+f[i-1][j-k])%mod;
                //状态转移,即对前i种花可摆放情况迭代计算
                //k从0开始,直到j-a[i]摆完,显然作为极限总方案数必须大于0
            }
        }
    }
    ::printf("%d",f[n][m]);

严不严格递增子列:

    int n;
    ::scanf("%d",&n);
    int L[n];
    for (int i = 0; i < n; ++i) {
        ::scanf("%d",&L[i]);
    }
    int dp[n];
    for (int i = 0; i < n; ++i) {
        dp[i]=1;
    }
    for (int i = 1; i < n; ++i) {
        for (int j = 0; j < i; ++j) {
            if((L[i]>=L[j])&&(dp[j]>=dp[i])){
                dp[i]=dp[j]+1;
            }
        }
    }
    int res=1;
    for (int i = 0; i < n; ++i) {
        res=((res>=dp[i])?res:dp[i]);
    }
    ::printf("%d",res);

开辟dp,存储以i结尾的子列最大长度.一遍遍遍历中得到所有最大长度,通过循环初始化.


拆数字:

    int n;
    ::scanf("%d",&n);
    int dp[100]={0};
    dp[0]=0;
    dp[1]=0;
    dp[2]=1;
    for (int i = 3; i <= n; ++i) {
        for (int j = 1; j < i; ++j) {
            dp[i]= max(j*(i-j),j*dp[i-j],dp[i]);
        }
    }
    ::printf("%d",dp[n]);

dp[i]动态更新,不拆,拆两个,拆多个;0 0 1 2 4 6 9 12 18 27 36


能量聚合,区间dp:

#include<iostream>
using namespace std;
#include<stdio.h>
int max(int a,int b){
    return a>b?a:b;
}
int main(){

    int n;
    ::scanf("%d",&n);
    int N=199;
    int a[N]; // head
    int dp[N][N]; //[区间]内合成的最大值

    for (int i = 1; i <= n; ++i) {
        ::scanf("%d",&a[i]);
        a[i+n]=a[i];
    }

    for (int i = 3; i <= n+1; ++i) { //length or number
        for (int j = 1; j+i <= 2*n+1; ++j) { //start
            int end=i+j-1;//end
            for (int k = j+1; k < end; ++k) {
                dp[j][end]= max(dp[j][end],dp[j][k]+dp[k][end]+a[j]*a[k]*a[end]);
            }
        }
    }

    int res=0;
    for (int i = 1; i <= n; ++i) {
        res= max(res,dp[i][i+n]);
    }

    ::printf("%d",res);
}

暴力迭代.


沙丘,区间和,区间dp:
 

int min(int a, int b) {
    return a < b ? a : b;
}
int main() {

    int n;
    ::scanf("%d", &n);
    int N = 310;
    int a[N]; // heap
    int dp[N][N]; //[区间]内合成的最大值
    int sum[N];
    memset(dp,0x3f, sizeof(dp)); // string.h
    for (int i = 1; i <= n; ++i) {
        ::scanf("%d", &a[i]);
        sum[i]=sum[i-1] + a[i];
        dp[i][i]=0;
    }

    for (int i = 2; i <= n; ++i) { //length or number
        for (int j = 1; j + i <= n + 1; ++j) { //start
            int end = i + j - 1;//end
            for (int k = j; k < end; ++k) {
                dp[j][end]= min(dp[j][end],dp[j][k]+dp[k+1][end]+sum[end]-sum[j-1]);
            }
        }
    }

    ::printf("%d", dp[1][n]);
}

n^3 暴力迭代

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值