zoukankan      html  css  js  c++  java
  • 区间dp

    区间dp 一般格式为“枚举中间点”

    即dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+fuckuniverse);

    比较经典的问题就是合并石子

    设有N堆沙子排成一排,其编号为1,2,3,…,N(N<=300)。每堆沙子有一定的数量,可以用一个整数来描述,现在要将这N堆沙子合并成为一堆,每次只能合并相邻的两堆,合并的代价为这两堆沙子的数量之和,合并后与这两堆沙子相邻的沙子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同,如有4堆沙子分别为 1  3  5  2 我们可以先合并1、2堆,代价为4,得到4 5 2 又合并 1,2堆,代价为9,得到9 2 ,再合并得到11,总代价为4+9+11=24,如果第二步是先合并2,3堆,则代价为7,得到4 7,最后一次合并代价为11,总代价为4+7+11=22;问题是:找出一种合理的方法,使总的代价最小。输出最小代价。

    #include <bits/stdc++.h>
    using namespace std;
    const int  N = 310;
    int dp[N][N];
    int a[310],sum[310];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
        for(int l=1;l<=n;l++)
            for(int i=1;i+l<=n;i++)
            {
                int j=i+l;
                dp[i][j]=23333333;
                for(int k=i;k<=j;k++)dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
            }
        cout<<dp[1][n];
        return 0;
    }

    另外就是能量项链 小技巧

    zzz

    一定要枚举每个区间最后合并的一个

    #include<iostream>
    #include<queue>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,a[500],dp[500][500];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){scanf("%d",&a[i]);a[i+n]=a[i];}
        for(int j=2;j<=2*n-1;j++)
            for(int i=j-1;i>0 && j-i<n;i--)
                for(int k=i;k<j;k++)dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1]);
        int mx=-1;
        for(int i=1;i<=n;i++)mx=max(dp[i][i+n-1],mx);
        cout<<mx;
        return 0;
    }
  • 相关阅读:
    语言基础
    进制转换
    Java基础相关
    Java基础了解
    php 条件查询和多条件查询
    php 增删改查练习
    php 用封装类的方法操作数据库和批量删除
    php 用面向对象的方法对数据库增删改查
    php 面向对象的方式访问数据库
    OOP 7大原则
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/7552996.html
Copyright © 2011-2022 走看看