博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
区间DP入门题目合集
阅读量:4565 次
发布时间:2019-06-08

本文共 5251 字,大约阅读时间需要 17 分钟。

 
区间DP主要思想是先在小区间取得最优解,然后小区间合并时更新大区间的最优解。
 
 
 
基本代码:
//mst(dp,0) 初始化DP数组for(int i=1;i<=n;i++){    dp[i][i]=初始值}for(int len=2;len<=n;len++)  //区间长度for(int i=1;i<=n;i++)        //枚举起点{    int j=i+len-1;           //区间终点    if(j>n) break;           //越界结束    for(int k=i;k

 

 
 
 
 
 
【题目描述】
N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。
例如: 1 2 3 4,有不少合并方法
1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)
1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)
1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)
 
Sample Input
41234
Sample Output
19
 
 
预处理出区间和,然后枚举每个长度的区间和断点,转移即可。
f[i][j] = min(f[i][j], f[i][k]+f[k+1][j]+sum[j]-sum[i-1])
 
#include 
#include
#include
#include
#include
using namespace std;typedef long long LL;const int maxn = 1000 + 100;#define INF 0x3f3f3f3fint main(){ int n; scanf("%d", &n); int sum[maxn]; int f[maxn][maxn]; memset(f, 0, sizeof(f)); for (int i = 1; i <= n; i++) { int x; scanf("%d", &x); sum[i] = sum[i-1]+x; } for (int len = 2; len <= n; len++) { for (int i = 1; i <= n; i++) { int j = i+len-1; f[i][j] = INF; for (int k = i; k < j; k++) f[i][j] = min(f[i][j], f[i][k]+f[k+1][j] + sum[j] - sum[i-1]); } } printf("%d\n", f[1][n]);}
View Code

 

 

 

 题意:

有一根长度为 n 的木棍,m 个可以切开的位置。

如果把一个长木棍切成两根短木棍,那么花费就是那根长木棍的长度。

求把这根木棍按照 m 个切点全部切开的最小花费。

 

#include 
#include
#include
#include
#include
using namespace std;#define maxn 100 + 100#define INF 0x3f3f3f3fint main(){ int n, m; while(scanf("%d%d", &n, &m) == 2 && n) { int x[maxn]; for (int i = 1; i <= m; i++) scanf("%d", &x[i]); x[0] = 0, x[m+1] = n; int f[maxn][maxn]; for (int i = 0; i <= m+1; i++) { for (int j = 0; j <= m+1; j++) f[i][j] = INF; f[i][i+1] = 0; } for (int len = 2; len <= m+1; len++) for (int i = 0; i+len <= m+1; i++) { int j = i+len; for (int k = i+1; k < j; k++) f[i][j] = min(f[i][k] + f[k][j] + x[j] - x[i], f[i][j]); } printf("The minimum cutting is %d.\n", f[0][m+1]); }}
View Code

 

 
 
有一串首位相连的环形能量珠项链,每个能量珠由头部和尾部组成。相邻的能量珠必定是某一个的头部 = 另一个的尾部。
可以把两个相邻的能量珠(a,b)(b,c)合成一个新的能量珠(a, c),并且释放 a * b * c的能量。
操作这串能量珠能够获得的最大的总能量是多少?

样例中,四个能量珠分别为(2, 3) (3, 5) (5, 10) (10, 2)

 

 

对于环形区间,我们只要把它展开成线形区间进行DP,然后取 dp[i, i+n-1] 中的最大值就可以了。

#include 
#include
#include
#include
using namespace std;#define maxn 200 + 100#define INF 0x3f3f3f3fint main(){ int n; while(~scanf("%d", &n)) { int a[maxn], sum[maxn], f[maxn][maxn]; memset(sum, 0, sizeof(sum)); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); a[n+i] = a[i]; } a[2*n+1] = a[1]; for (int i = 1; i <= 2*n; i++) for (int j = i; j <= 2*n; j++) f[i][j] = 0; for (int len = 2; len <= 2*n; len++) for (int i = 1; i+len-1 <= 2*n; i++) { int j = i+len-1; for (int k = i; k < j; k++) f[i][j] = max(f[i][j], f[i][k] + f[k+1][j] + a[i]*a[k+1]*a[j+1]); } int ans = 0; for (int i = 1; i <= n; i++) ans = max(ans, f[i][i+n-1]); printf("%d\n", ans); }}
View Code

 

 

 

也是普通的环形区间DP,拆环为链。

然而这样过不了的。因为数据范围是2000,n^3的DP会TLE。

所以需要用平行四边形优化。

这个玩意我还没有看懂,只是拿过来用。以后慢慢理解。

 

#include 
#include
#include
#include
using namespace std;#define maxn 2000 + 100#define INF 0x3f3f3f3fint main(){ int n; while(~scanf("%d", &n)) { int a[maxn], sum[maxn], f[maxn][maxn], s[maxn][maxn]; memset(sum, 0, sizeof(sum)); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); a[n+i] = a[i]; } for (int i = 1; i <= 2*n; i++) sum[i] = sum[i-1] + a[i]; for (int i = 1; i <= 2*n; i++) { f[i][i] = 0; s[i][i] = i; //这里的s数组也要初始化 for (int j = i+1; j <= 2*n; j++) f[i][j] = INF; } for (int len = 2; len <= 2*n; len++) for (int i = 1; i+len-1 <= 2*n; i++) { int j = i+len-1; for (int k = s[i][j-1]; k <= s[i+1][j]; k++) //单调性枚举 { int tmp = f[i][k] + f[k+1][j] + sum[j] - sum[i-1]; if (tmp < f[i][j]) { f[i][j] = tmp; s[i][j] = k; } } } int ans = INF; for (int i = 1; i <= n; i++) ans = min(ans, f[i][i+n-1]); printf("%d\n", ans); }}
View Code

 

 

转载于:https://www.cnblogs.com/ruthank/p/8881817.html

你可能感兴趣的文章
如何在windows xp professional安装iis的解决方法
查看>>
抽象类和接口
查看>>
使用ASP.NET Atlas AutoComplete Behavior或AutoComplete Extender实现自动完成功能(下)
查看>>
golang 常见疑惑总结
查看>>
8大你不得不知的Android调试工具
查看>>
pc端元素拖拽
查看>>
Sublime Text3使用Package Control 报错There Are No Packages Available For Installation
查看>>
判断连通图是否有环(并查集)
查看>>
汽车之家面试题2016
查看>>
POJ-数据结构-优先队列模板
查看>>
【HAOI2006】旅行(并查集暴力)
查看>>
css实现文本超出部分省略号显示
查看>>
留言板
查看>>
vue-router组件状态刷新消失的问题
查看>>
Android UI开发第十四篇——可以移动的悬浮框
查看>>
java8的一些用法
查看>>
(十)Hive分析窗口函数(二) NTILE,ROW_NUMBER,RANK,DENSE_RANK
查看>>
2018-11-19站立会议内容
查看>>
STM32 通用定时器相关寄存器
查看>>
【题解】1621. 未命名
查看>>