P1064 [NOIP2006 提高组] 金明的预算方案

题意:

每个物品有价格和价值,物品之间存在依赖关系(单向的),现在又n元钱,买哪些物品,即满足依赖关系又使得每件物品的价格与价值的乘积的总和最大
(每个主件最多两个附件)

题解:

方法一:
学习博客
因为每个主件最多两个附件,且附件必须依赖于主件,所以对每个主件一共就五种决策:
1.不选,然后考虑下一个
2.选择且只选主件
3.选择这个主件,且选择附件1
4.选择这个主件,且选择附件2
5.选择这个主件,且选择附件1,2
我们设变量fv[i][j]表示主件为i的第j个附件的价值与重量乘积
fw[i][j]表示主件为i的第j个附件的重量
dp[i]就是01背包中的设定
我们仿照01背包对上面5种情况列出转移方程

     //情况1:只要主件 和啥都不要比较   dp[j]=max(dp[j],dp[j-mw[i]]+mv[i]);  //情况2:主件和附件1 和上面选出的较大值比较   if(j>=mw[i]+fw[i][1])dp[j]=max(dp[j],dp[j-mw[i]-fw[i][1]]+mv[i]+fv[i][1]);  //情况3:主件和附件2 和上面选出的较大值比较   if(j>=mw[i]+fw[i][2])dp[j]=max(dp[j],dp[j-mw[i]-fw[i][2]]+mv[i]+fv[i][2]);  //情况4:都要   if(j>=mw[i]+fw[i][1]+fw[i][2])  dp[j]=max(dp[j],dp[j-mw[i]-fw[i][1]-fw[i][2]]+mv[i]+fv[i][1]+fv[i][2]);

方法2:
学习文章
根据依赖关系我们可以得知这是一个树型结构,这个树的特点:
一个物品所依赖的所有物品都是他的父节点
如果一个物品不选,对应到树上,他所有的子节点都不能选
现在我们如何用01背包来解决这个树形问题
我们可以将树转化成链,通过dfs序实现
对树求后序遍历,后序遍历的顺序是前后中,也就是一个节点的儿子和左兄弟都在他前面
这样我们可以有以下决策:
1.选当前物品,状态i由i-1(从儿子)转移而来
2.不选择,这个点的儿子也不能选,那状态只能从前面最近的左兄弟转移
pre[u]表示编号为u的左兄弟的编号
dp[i][j]=max(dp[pre[i]][j],dp[i-1][j-v]+w)
总复杂度为O(n+nm),关键是这个方法可以解决附件上有附加的情况,能处理情况更广
不过我对这个方法还不是完全理解。。有待消化

代码:

#include<iostream>
using namespace std;
int m,n,mw[33333],mv[33333],fw[33333][3],fv[33333][3],dp[33333],v,p,q;
//mw主件重量,mv主件价值,fw主件对应的附件重量,fv主副价值,n总重量,m总个数
int main()
{  cin>>n>>m;  for(int i=1;i<=m;i++){  cin>>v>>p>>q;  if(!q){//如果是主件   mw[i]=v;//主件重量   mv[i]=v*p;//主件价值与重量乘积   }  else{//如果是附件   fw[q][0]++;//记录主件的附件个数(只记录在fw就行,fv那里没用   fw[q][fw[q][0]]=v;//主件的个数是用来确定该附件应该填在第一个还是第二个格子里   fv[q][fw[q][0]]=v*p;//(是第一个还是第二个附件)   }  }  for(int i=1;i<=m;i++)  for(int j=n;j>=mw[i];j--){//01背包模板   //每一个if的前提是背包能不能装下该物品   //情况1:只要主件 和啥都不要比较   dp[j]=max(dp[j],dp[j-mw[i]]+mv[i]);  //情况2:主件和附件1 和上面选出的较大值比较   if(j>=mw[i]+fw[i][1])dp[j]=max(dp[j],dp[j-mw[i]-fw[i][1]]+mv[i]+fv[i][1]);  //情况3:主件和附件2 和上面选出的较大值比较   if(j>=mw[i]+fw[i][2])dp[j]=max(dp[j],dp[j-mw[i]-fw[i][2]]+mv[i]+fv[i][2]);  //情况4:都要   if(j>=mw[i]+fw[i][1]+fw[i][2])  dp[j]=max(dp[j],dp[j-mw[i]-fw[i][1]-fw[i][2]]+mv[i]+fv[i][1]+fv[i][2]);  }  //输出在价值为n时能得到的最大值   cout<<dp[n]<<endl;  return 0;
}
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 64;
const int maxm = maxn;
const int maxv = 33333;
struct Node{//表示物品int v,w;Node() = default;Node(int a,int b):v(a),w(b){}
}d[maxn],t[maxn];
struct Edge{int from,to;Edge() = default;Edge(int a,int b):from(a),to(b){}
}Edges[maxm];
int head[maxn],nxt[maxm],root[maxn],rp;
inline void addedge(int from,int to){static int tot;Edges[++tot] = Edge(from,to);nxt[tot] = head[from];head[from] = tot;
}
int pre[maxn],f[maxn][maxv],p = 0;
void dfs(int u){int tp = p;//由于后序遍历的性质,一个点的左兄弟显然是进入这个点时序列中的最后一个点for(int i = head[u];i;i = nxt[i]){Edge &e = Edges[i];dfs(e.to);}d[++p] = t[u];//后序遍历pre[p] = tp;//求左兄弟,注意,pre[t]表示序列中编号为t的节点的左兄弟的编号
}
int n,m;
int main(){scanf("%d %d",&m,&n);for(int i = 1;i <= n;i++){//建图int v,w,faz;scanf("%d %d %d",&v,&w,&faz);t[i] = Node(v,v * w);//先预处理它的权值addedge(faz,i);//有个技巧,如果一个点是主件,我们就认为它依赖于虚拟点0}dfs(0);for(int i = 1;i <= n;i++)//dp求解for(int j = 0;j <= m;j++)if(j >= d[i].v)f[i][j] = max(f[pre[i]][j],f[i - 1][j - d[i].v] + d[i].w);else f[i][j] = f[pre[i]][j];//转移 printf("%d\n",f[n][m]);return 0;
}

P1064 [NOIP2006 提高组] 金明的预算方案相关推荐

  1. 信息学奥赛一本通 1844:【06NOIP提高组】金明的预算方案 | 洛谷 P1064 [NOIP2006 提高组] 金明的预算方案

    [题目链接] ybt 1844:[06NOIP提高组]金明的预算方案 洛谷 P1064 [NOIP2006 提高组] 金明的预算方案 [题目考点] 1. 动态规划:分组背包 2. 动态规划:依赖背包 ...

  2. 【背包DP练习】洛谷 P5020货币系统 P1757通天之分组背包 P1064[NOIP2006 提高组]金明的预算方案 P5322 [BJOI2019]排兵布阵

    洛谷 P5020货币系统 https://www.luogu.com.cn/problem/P5020 思路是把货币从小到大排序,然后按顺序依次完全背包dp,每次dp检查i-1种面值的货币能不能凑出第 ...

  3. noip2006提高组-金明的预算方案解题报告

    这是一道有依赖的背包的经典题目,考虑到每个物品最多有两个子物品,最多会有四种状态,所以可以转化为01背包进行枚举状态 View Code 1 #include<stdio.h> 2 #in ...

  4. 依赖背包dp NOIP2006 vijos 1313 金明的预算方案

    依赖背包: 简化的问题 这种背包问题的物品间存在某种"依赖"的关系.也就是说,物品i依赖于物品j,表示若选物品i,则必须选物品j.为了简化起见,我们先设没有某个物品既依赖于别的物品 ...

  5. bsoj 1512 金明的预算方案(树型DP)

    [NOIP 2006提高]金明的预算方案   Time Limit:10000MS  Memory Limit:65536K Total Submit:485 Accepted:222  Case T ...

  6. P1064 金明的预算方案

    P1064 金明的预算方案 题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置 ...

  7. [LuoguP1064][Noip2006]金明的预算方案

    金明的预算方案(Link) 题目描述 现在有\(M\)个物品,每一个物品有一个钱数和重要度,并且有一个\(Q\),如果\(Q = 0\),那么该物件可以单独购买,当\(Q != 0\)时,表示若要购买 ...

  8. 算法提高 金明的预算方案

    算法提高 金明的预算方案   时间限制:1.0s   内存限制:256.0MB      问题描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是, ...

  9. [动态规划] 洛谷P1064 金明的预算方案

    洛谷P1064 金明的预算方案 题意: 每件物品都有一定的满意度,而且物品分主件附件,要买附件就必须要买主件,但是买主件不一定要买附件(一个主件最多有两个附件,也可能没有喔) 设第j件物品的价格为v[ ...

最新文章

  1. mac os x常用快捷键及用法
  2. Linux grep,egrep及相应的正则表达式用法详解
  3. 电视信号——行场同步
  4. java多线程系列(四)---ReentrantLock的使用
  5. java质因数算法_Java分解任意输入数的质因数算法的实现示例
  6. 第三次作业-结对编程
  7. Java基础(三十五)Math、Random类和数字格式化(String.format方法)
  8. tiny4412 SDK1312B LED驱动
  9. LUA面向对象编程技巧
  10. Monty Hall 问题与贝叶斯定理的理解
  11. 第二部分 设计类型:第13章 接口
  12. C语言线程创建与锁机制
  13. 不能从const char *转换为LPCWSTR --VS经常碰到
  14. POJ3262 Protecting the Flowers【贪心】
  15. FIT2CLOUD飞致云面试总结
  16. 新·自学日语教材推荐加点评
  17. 美国电影超短200句(看英文原版电影很有用的!)(转)
  18. 【20210805】【数据分析】标称型数据和数值型数据
  19. TensorFlow c++ SessionFactory注册与No session factory registered错误
  20. Pjsip信令超时机制修改

热门文章

  1. 4-8岁那些最难的数学概念,美国老师用一套绘本让孩子秒懂
  2. 32位hex转浮点 python_python——int()、hex()、oct()、bin()、float()数值类型转换函数
  3. ubuntu运行python ide_在Ubuntu-16.04中安装Python可视化IDE——Spyder
  4. java前补零工具类_java生成编码工具类,不足补0
  5. oracle取位置,获取oracle trace文件路径
  6. c语言中二重指针如何赋值,关于二重指针释放的有关问题
  7. python中的while语句怎么居中_python基础之while语句操作
  8. 7-3 模板题 (10 分)(思路+详解)
  9. 695.岛屿的最大面积(026)BFS
  10. 7-22 堆栈模拟队列 (25 分)(详解夹思路)