DAG模型
数字三角形:
1、递归计算
int solve(int i,int j) {
return a[i][j] +(i==n?:max(solve(i+,j),solve(i+,j+)));
}
2、记忆化搜索,不用指明计算顺序,并且保证每个状态只计算一次
int solve(int i,int j) {
if(d[i][j]>=) return d[i][j];
return d[i][j] = a[i][j] +(i==n?:max(solve(i+,j),solve(i+,j+)));
}
3、递推计算
for(int j=;j<=n;j++)
d[n][j] = a[n][j]; for(int i=n-;i>=;i--) {
for(int j=;j<=i;j++) {
d[i][j] = a[i][j] + max(d[i+][j],d[i+][j+]);
}
}
刘汝佳紫书P262
嵌套矩形问题:
典型的二元关系,用图来建模,要是x可以嵌套在y里面,就x->y连线,这个图是有向无环图,有向可以理解,无环的意思就是说,一个矩形不可能直接或者间接的把自己嵌套起来。
问题: 求最多嵌套多少?
就是在这个图上求一个最长路
同数字三角形那样,d(i)表示从节点I出发的最长路的长度
那么d(i) = max{(d[j]+1)|(i,j)ŒE};最后遍历一遍d(i);
#include <bits/stdc++.h>
using namespace std;
#define maxn 10000 int G[maxn][maxn];
int dp[maxn];
int n; //n个节点 //DAG
int DAG(int i) { int &ans = dp[i];
if(ans>)
return ans;
ans = ;
for(int j=;j<=n;j++) {
if(G[i][j])
ans = max(ans,DAG(j)+);
}
return ans;
} void print_ans(int i) { printf("%d ",i);
for(int i=;i<=n;i++) {
if(G[i][j]&&d[i]==d[j]+) {
print_ans(j);
break;
}
}
} int main()
{ memset(dp,,sizeof(dp));
//建图 for(int i=;i<=n;i++)
DAG(i); int ans = -;
int f = -;
for(int i=;i<=n;i++)
{
if(ans<dp[i]) {
ans = dp[i];
f = i;
}
}
print_ans(i); return ;
}
硬币问题:(固定了终点,状态起点是S,状态终点是0)
最长路,最短路。
代码编译不能过,很多函数写同名了,主要记录思想。
以 i 出发的最长路:d(i) = max(d(j)+1|(i,j)<E)
以 i 结束的最长路:d(i) = max(d(j)+1|(j,i)<E)
推荐方案二。
对于方案一,代码细节难度有一点高。
第一: S = 0,本身是可以的,所以dp[N]初始化-1;然后遇到没有计算的,ans = 0;是错误的,原因:节点S不一定到达0状态,但是返回值却是0,而0却可以是别的含义,就是S = 0,不用拿硬币。所以ans = -INF;
用vis数组会方便很多,思路清晰,保证每个状态只访问一次。而且不用担心特殊值之间的冲突了。
然后,求最大,最小两个值,记忆化搜索要写两个。
这时可以递推。注意递推顺序。得到minv,maxv数组,这是可以像记忆化搜索那样搜索路径。
minv[S] ==minv[S-v[j]] + ;
printf("%d ",j);
但是有更好的方案:
就是找到局部最优方案时记录路径。
min_coin[i] = j;
max_coin[i] = j;
然后递归打印,这样就不用循环遍历了
void print_ans(int *min_coin,int S) {
while(S) {
printf("%d ",min_coin[S]);
S-=v[min_coin[S]];
}
}
下面是全部代码:
//固定终点的最长路和最短路 #include <bits/stdc++.h> using namespace std; #define N 10000
#define INF 0x3f3f3f3f const int v[] = {,,,,,,,};
int n; //硬币总数
int S; //总钱数 int dp[N];
bool vis[N]; int dp(int S) { int & ans = dp[S];
if(ans!=-) return ans; ans = -(<<);
for(int i=;i<=n;i++) {
if(S>=v[i])
ans = max(ans,dp(S-v[i])+);
}
return ans;
} //dp方案二,利用vis数组标记状态
int dp(int S) { if(vis[S]) return dp[S];
vis[S] = ; int & ans = dp[S];
ans = -(<<);
for(int i=;i<=n;i++) { if(S>=v[i])
ans = max(ans,dp(S-v[i])+);
}
} void print_ans(int *d,int S) { for(int i=;i<=n;i++) { if(S>=v[i]&&d[S]==d[S-v[i]]+) {
printf("%d ",i);
print_ans(d,S-v[i]);
break;
} } } //改进的print_ans()
void print_ans(int &min_coin,int S) { while(S) {
printf("%d ",min_coin[S]);
S-=v[min_coin[S]];
} } int main()
{
scanf("%d",&S);
memset(vis,,sizeof(vis));
memset(dp,-,sizeof(dp)); int ans = dp(S);
if(ans!=(<<))
printf("OK"); int minv[N] = {};
int maxv[N] = {}; minv[] = maxv[] = ;
for(int i= ;i<=S;i++) {
minv[i] = INF;
maxv[i] = -INF;
} for(int i=;i<=S;i++) {
for(int j=;j<=n;j++) {
if(i>=v[j]) {
minv[i] = min(minv[i],minv[i-v[j]]+);
maxv[i] = max(maxv[i],maxv[i-v[j]]+);
}
}
} printf("%d %d\n",minv[S],maxv[S]); print_ans(minv,S);
print_ans(maxv,S); //空间换时间 int min_coin[N];
int max_coin[N]; for(int i=;i<=S;i++) {
for(int j=;j<=n;j++) { if(i>=v[j]) {
if(minv[i]>minv[i-v[j]]+) {
minv[i] = minv[i-v[j]]+;
min_coin[i] = j;
}
if(maxv[i]<maxv[i-v[j]]+) {
maxv[i] = maxv[i-v[j]] + ;
max_coin[i] = j;
} } } } return ;
}
DAG模型的更多相关文章
- UVA103 dp基础题,DAG模型
1.UVA103 嵌套n维空间 DAG模型记忆化搜索,或者 最长上升子序列. 2.dp[i]=max( dp[j]+1),(第i个小于第j个) (1) //DAG模型记忆化搜索 #include< ...
- NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索
矩形嵌套 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a& ...
- DAG模型——嵌套矩阵
有向无环图上的动态规划是学习动态规划的基础,很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 嵌套矩阵 有n个矩阵,每个矩阵可以用两个整数a,b描述,表示它的长和宽.矩阵X(a,b)可以嵌 ...
- DAG模型——硬币问题
硬币问题 有n种硬币,面值分别为V1,V2,...,Vn,每种都有无限多.给定非负整数S,可以选用多少个硬币,使得面值之和恰好为S?输出硬币数目的最小值和最大值.1<=n<=100, 0& ...
- DAG 模型 stacking boxes 动态规划
题目:UVA 103 stacking boxes 题目大意: 给你两个数,一个是盒子的个数,一个是每一个盒子的维数.将一个个盒子互相装起来,让你求最多可以装多少个,要求字典序最小. 解析:这个就是盒 ...
- DAG模型(矩形嵌套)
推荐在线例题:http://acm.nyist.net/JudgeOnline/problem.php?pid=16 题摘: 矩形嵌套 时间限制:3000 ms | 内存限制:65535 KB 难 ...
- DAG 动态规划 巴比伦塔 B - The Tower of Babylon
题目:The Tower of Babylon 这是一个DAG 模型,有两种常规解法 1.记忆化搜索, 写函数,去查找上一个符合的值,不断递归 2.递推法 方法一:记忆化搜索 #include < ...
- hdu 1069 DAG加权
题目: Monkey and Banana Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...
- DAG上dp思想
DAG上DP的思想 在下最近刷了几道DAG图上dp的题目.要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点.第二道是洛谷上的NOI导刊题 ...
随机推荐
- JavaOOP QuickHit项目分析
项目需求:游戏等级6级,随机字符串每级长度不同.每升一级减少比较次数,但是字符串长度相应增加!每级总分数不同,如果游戏中途输入错误则游戏退出!玩家每次在规定时间内输入字符串的同时,打印出游戏难度等级. ...
- 访问网页时提示的503错误信息在IIS中怎么设置
访问网页时提示的503错误信息在IIS中怎么设置 503是一种常见的HTTP状态码,出现此提示信息的原因是由于临时的服务器维护或者过载,服务器当前无法处理请求则导致了访问网页时出现了503错误.那么当 ...
- Aspose.cell处理Excel
(一)从数据库中读取数据写入Excel中 方法1: 步骤:1.建立一个新的项目,引用动态链接库Aspose.dll 2.见下面的原代码 using System;using System.Collec ...
- 夺命雷公狗---DEDECMS----7dedecms目录结构
我们dedecms的目录结构其实只需要一张图即可明了了,如下图所示:
- z/os上的tar和gzip(2)
前一篇文章写过了如何合成并压缩大批量文件,这篇文章解释一下如何在拿到压缩文件后如何解压并还原大批量文件. 解压缩的JCL很简单,如下所示,和压缩的JCL类似,只要把参数改成UNPACK,然后设置一 ...
- 打开了chrome审查元素 发现报错 Uncaught SyntaxError: Unexpected token )
这个错误并不影响业务处理,但是看到有报错,心里总是不爽. 经过几番查找,发现了原因. <a href="javascript:void()" oncick="onS ...
- SqlServer 中如何查看某一个Sql语句是复用了执行计划,还是重新生成了执行计划
我们知道SqlServer的查询优化器会将所执行的Sql语句的执行计划作缓存,如果后续查询可以复用缓存中的执行计划,那么SqlServer就会为后续查询复用执行计划而不是重新生成一个新的执行计划,因为 ...
- 什么是BI(Business Intelligence)【转】
谈谈对BI的理解,从BI的定义.基本技术.专业名词.实例应用及扩展等方面进行重新描述,巩固对BI的理解. 一.BI的定义 BI是Business Intelligence的英文缩写,中文解释为商务智能 ...
- django models数据类型
Django Models的数据类型 AutoField IntegerField BooleanField true/false CharField maxlength,必填 TextField C ...
- 解析XML的四种方式
四种操作xml的方式: SAX, DOM, JDOM , DOM4J的比较 1. 介绍 1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官 ...