首页 > 代码库 > nyoj 737 石子合并(一)。区间dp
nyoj 737 石子合并(一)。区间dp
http://acm.nyist.net/JudgeOnline/problem.php?pid=737
数据很小,适合区间dp的入门
对于第[i, j]堆,无论你怎么合并,无论你先选哪两堆结合,当你把[i, j]合成一堆的那一步的时候,花费肯定就是sum[i....j]
可以用纸模拟下。
那么我们设dp[i][j]表示把i...j堆合成一堆的时候的最小花费。
比如dp[1][1] = 0。dp[1][2] = a[1] + a[2];
那么要求dp[i][j],则可以是dp[i][k] + dp[k + 1][j] + cost
注意dp的时候的顺序,因为要求dp[1][n],则需要用到dp[1][k]和dp[k][n]
你需要考虑下怎么for,才能使得子问题已经被算出,建议一开始用dfs + 记忆化做。
这里dp的顺序应该是先算出2个集合的,3个、4个、......
就是先算出dp[1][2], dp[2][3],这使得求dp[1][3]成为可能。
all dp[i][i] = 0
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 200 + 20; int n; int a[maxn]; int dp[maxn][maxn]; int sum[maxn]; int dfs(int be, int en) { if (be > en) return 0; if (be == en) { return dp[be][en] = 0; } if (dp[be][en] != inf) return dp[be][en]; for (int k = be; k <= en; ++k) { dp[be][k] = dfs(be, k); dp[k + 1][en] = dfs(k + 1, en); assert(dp[be][k] >= 0); assert(dp[k + 1][en] >= 0); dp[be][en] = min(dp[be][k] + dp[k + 1][en] + sum[en] - sum[be - 1], dp[be][en]); // cout << dp[2][3] << endl; } return dp[be][en]; } void work() { for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); sum[i] = sum[i - 1] + a[i]; } memset(dp, 0, sizeof dp); // cout << dfs(1, n) << endl; // cout << dp[2][3] << endl; for (int k = 1; k <= n - 1; ++k) { for (int i = 1; i <= n - 1; ++i) { int be = i; int en = i + k; if (en > n) break; dp[be][en] = inf; for (int h = be; h <= en - 1; ++h) { dp[be][en] = min(dp[be][en], dp[be][h] + dp[h + 1][en] + sum[en] - sum[be - 1]); } } } printf("%d\n", dp[1][n]); } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif while (scanf("%d", &n) != EOF) work(); return 0; }
nyoj 737 石子合并(一)。区间dp
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。