洛谷P1622释放囚犯

题目

这个题很明显是一个区间DP,但是比较不同的是,这个题它很像区间DP的经典题——石子合并。

然后我傻傻的搞了这个题搞了一下午,然后几乎看遍了全网的题解,就只看懂了这个方法,可能是我太菜了吧,但是我还是不懂别人的题解为什么区间DP的右端点可以在左端点左边啊

因此我们可以先转化成石子合并,然后还要注意一些坑点,就比如这个j-i-1指j-i这段区间内除去端点之间的数的个数。

#include <bits/stdc++.h>
#include <cstdio>
using namespace std;
//71404
int p, q;
int data[100100], sum[100010], n, e[100010], dp[1100][1100];
int main()
{
    scanf("%d%d", &p, &q);
    for(int i = 1; i <= q; i++)
        scanf("%d", &data[i]);
    sort(data + 1, data + 1 + q);
        data[++q] = p + 1;//这样好处理前缀和, 因为要分割q条线,因此有q + 1个石头
    for(int i = 1; i <= q; i++)
        sum[i] = sum[i - 1] + data[i] - data[i - 1] - 1;//先转变成石子合并的方式
    for(int i = q; i >= 1; i--)
        for(int j = i + 1; j <= q; j++)
        {
            dp[i][j] = 10000000;
            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] + j - i - 1);
        }        printf("%d", dp[1][q]);
}

 

posted @ 2018-10-15 17:08  DAGGGGGGGGGGGG  阅读(240)  评论(0编辑  收藏  举报