动态规划_DAG模型
来源:互联网 发布:数控车床g41编程实例 编辑:程序博客网 时间:2024/05/18 12:00
DAG(有向无环图)上的动态规划是学习动态规划的基础。
- 最长路及其字典序
- 固定终点的最长路和最短路
*1.嵌套矩形问题*
有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a < c,b < d或者b < c,a < d(相当于旋转X90度)。例(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
—————————————————————
得动态转移方程:d(i)=max{d(j)+1 | (i,j)∈E}
其中E为边集。求解:
—————————————————————
//现假设邻接矩阵已求出,存放在矩阵G中。int dp(int i) { int& ans = d[i];//引用,方便对于d[i][j][k][l][m][n]的书写 if(ans > 0) return ans;//若已赋值,无需再次计算 ans = 1; for(int i=0; j<=n; j++) if(G[i][j])/*以构建DAG*/ ans = max(ans, dp(j)+1); return ans;//打印输出void print_ans(int i) { printf("%d", i); for(int j=1; j<=n; j++) if(G[i][j] && d[i]==d[j]+1) { print_ans(j); break; }}
*2.硬币问题(完全背包问题)*
n种硬币,面值分别为V1,V2,…Vn,每种都有无限多。给定非负整数S,可以选用多少个硬币,使得面值之和恰好为S?输出硬币数目的最小值和最大值。
//最长路的代码 | 【初始化】mamset(d, -1, sizeof(d)); | (有瑕疵)int dp(int S) { int& ans = d[S]; if(ans>=0) return ans; ans = 0; for(int i=0; i<=n; i++) if(S>=V[i]) ans = max(ans, dp(S-V[i])+1); return ans;}//【BUG】S不一定可到达0
//【修正】int dp(int S) { int& ans = d[S]; if(ans!=-1) return ans;//已赋值 ans = -(1<<30); for(int i=0; i<=n; i++) if(S>=V[i]) ans = max(ans, dp(S-V[i])+1); return ans;}//【TIPS】用特殊值(如-1)表示"未算过",则必须将其和其他特殊值(如无解)//区分开。求最大值时最好将初值设为"无穷小"。
//【可读性优化】用vis数组记录访问状态。用空间代价增强代码可读性,减少代码出错可能性。int dp(int S) { if(vis[S]) return d[S]; vis[S] = 1; int &ans = d[S]; ans = -(1<<30); for(int i=0; i<=n; i++) if(S>=V[i]) ans = max(ans, dp(S-V[i])+1); return ans;}
【递推】注意计算顺序和边界处理
minv[0] = maxn[0] = 0;for(int i=1; i<=S; i++) { minv[i] = INF; maxv[i] = -INF;}for(int i=1; i<=S; i++) for(int j=1; j<=n; j++) if(i>=V[j]) { minv[i] = min(minv[i], minv[i-V[j]]+1); maxv[i] = max(maxv[i], maxv[i-V[j]]+1); }printf("%d %d\n", minv[S], maxv[S]);
输出字典序最小的方案(状态的可逆)
//【递归打印】void print_ans(int* d, int S) { for(int i=1; i<=n; i++) if(S>=V[i] && d[S]==d[S-V[i]]+1) { printf("%d ", i); print_ans(d, S-V[i]); break; } }
//【递推打印】void print_ans(int* d, int S) { while(S) { printf("%d ", d[S]); S -= V[d[S]]; }}for(int i=1; i<=S; i++) for(int j=1; i<=n; j++) if(i>=V[j]) { if(min[i]>min[i-V[j]]+1) { min[i]=min[i-V[j]+1;//更新min,寻找最小的min min_coin[i]=j;//选择第j种硬币 } if(max[i]<max[i-V[j]]+1) { max[i]=max[i-V[j]+1; max_coin[i]=j; } }print_ans(min_coin, S);print_ans(max_coin, S);
对于某些不可逆的问题:
- “填表法”。对于每个状态i,找到f(i)依赖的所有状态。
- “刷表法”。对于每个状态i,更新f(i)所影响到的状态。
0 0
- 动态规划_DAG模型
- 动态规划_DAG模型
- 动态规划_DAG例题_A Spy in the Metro(UVA1025)
- 动态规划_DAG例题_The Tower of Babylon(UVA437)
- 动态规划_DAG例题_A Spy in the Metro(UVA1025)
- 动态规划_DAG例题_The Tower of Babylon(UVA437)
- 动态规划:矿工模型
- 动态规划 - 金矿模型
- 动态规划 嵌套模型
- DAG模型的动态规划
- 动态规划经典模型整理
- 算法 - 动态规划(通过金矿模型介绍动态规划)
- 通过金矿模型介绍动态规划 (动态规划入门)
- 【转载】通过金矿模型介绍动态规划 (动态规划入门)
- 通过金矿模型介绍动态规划
- 通过金矿模型介绍动态规划
- 通过金矿模型介绍动态规划
- 中文分词语言模型和动态规划
- 【bzoj1853】 SCOI2010幸运数字 容斥原理
- Qt 常用类(3)—— QString
- #pragma alloc_text 用法
- SVN客户端各菜单作用及常见符号
- RT9193 自我感觉不错的芯片
- 动态规划_DAG模型
- IOS基础:retain,copy,assign及autorelease
- Nginx goaccess 安装应用指南
- 关于iOS多线程
- 测试 有没有
- InputStreamReader和BufferedReader用法及真实案例
- 安卓在fragment里面使用TabHost布局
- glFlush,glFinish和SwapBuffers用法
- OC学习----NSURL