石子合并/能量项链【区间dp】
题目链接:http://www.51mxd.cn/problem.php-pid=737.htm
题目大意:给出n个石子堆以及这n个石子堆中石子数目,每次操作合并两个相邻的石子堆,代价为两个石子堆数目之和,求最后合成一个石子堆时所花费的最小代价。
解题思路:典型的区间dp
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define mem(a, b) memset(a, b, sizeof(a)) 5 const int MAXN = 220; 6 const int inf = 0x3f3f3f3f; 7 using namespace std; 8 9 int arr[MAXN], sum[MAXN]; 10 int dp[MAXN][MAXN]; //表示i ~ j区间内的最小代价 11 12 int main() 13 { 14 int n; 15 while(scanf("%d", &n) != EOF) 16 { 17 mem(dp, 0), mem(sum, 0); 18 for(int i = 1; i <= n; i ++) 19 { 20 scanf("%d", &arr[i]); 21 sum[i] += sum[i - 1] + arr[i]; 22 } 23 for(int len = 2; len <= n; len ++) //枚举长度 24 { 25 for(int i = 1; i + len - 1 <= n; i ++) // 枚举区间起点 26 { 27 int j = i + len - 1; //区间终点 28 dp[i][j] = inf; 29 for(int k = i; k < j; k ++) 30 { 31 dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]); 32 } 33 } 34 } 35 printf("%d\n", dp[1][n]); 36 } 37 return 0; 38 }
题目链接:https://ac.nowcoder.com/acm/contest/1089/J
题目大意:给出一个环形项链,每次操作合成两个相邻的宝珠,代价为两个宝珠首,中间,尾乘积,求最后合成一个宝珠时所花费的最小代价。
解题思路:
1.区间dp,破环成链,数组开2倍。
1 #include<stdio.h> 2 #define LL long long 3 #include<math.h> 4 #include<algorithm> 5 using namespace std; 6 const int MAXN = 220; 7 8 int a[MAXN]; 9 LL dp[MAXN][MAXN]; 10 11 int main() 12 { 13 int n; 14 scanf("%d", &n); 15 for(int i = 1; i <= n; i ++) 16 { 17 scanf("%d", &a[i]); 18 a[i + n] = a[i]; 19 } 20 for(int len = 2; len <= n; len ++) //枚举长度 21 { 22 for(int i = 1; i + len - 1 <= 2 * n; i ++) //枚举起点 23 { 24 int j = i + len - 1; //终点 25 for(int k = i; k < j; k ++) 26 { 27 dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + a[i] * a[k + 1] * a[j + 1]); 28 } 29 } 30 } 31 LL ans = -1; 32 for(int i = 1; i <= n; i ++) 33 ans = max(ans, dp[i][i + n - 1]); 34 printf("%lld\n", ans); 35 return 0; 36 }