题目:
这个题很明显是一个区间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]); }