区间DP 入门

首先我们先需要知道区间是如何用dp来做的,让我们来看一下模板。

1 for (int i = 1; i <= n; i++){//枚举区间里面的个数
2     for (int j = 1; j <= 能枚举到得最大的pos; j++){
3         int p = i + j - 1;//表示在目前能到达的最大值的坐标
4         if (p > n) break;
5         for (int k = j; k <= p; k++){
6             dp[j][p] = min or max(dp[j][p], dp[j][k] + dp[k + ][p] + j to p 的 val);
7         }
8     }
9 }
View Code

①石子问题

http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=737

这个就是很显然的模板题目了。

可以提前用sum[]来维护区间的和,或者也可以用树状数组维护。

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
const int maxn = 200 + 5;
const int inf = 0x3f3f3f3f;
int dp[maxn][maxn];
int a[maxn];
int sum[maxn];
int n;

int main(){
    while (scanf("%d", &n) == 1){
        for (int i = 1; i <= n; i++) scanf("%d", a + i);
        memset(dp, 0, sizeof(dp));
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; i++){
            sum[i] = sum[i - 1] + a[i];
        }
        for (int i = 2; i <= n; i++){
            for (int j = 1; j <= n - i + 1; j++){
                int p = j + i - 1;
                if (p > n) break;
                dp[j][p] = inf;
                for (int k = j; k <= p; k++){
                    dp[j][p] = min(dp[j][p], dp[j][k] + dp[k + 1][p] + sum[p] - sum[j - 1]);
                }
            }
        }
        printf("%d
", dp[1][n]);
    }
    return 0;
}
View Code

原文地址:https://www.cnblogs.com/heimao5027/p/5644970.html