原题链接:简化型背包
解题思路:
1、这个相单于数学的组合问题。
2、DFS可以看做是列出树状图,先从最大的大树0开始,他的子树有树1,树2,树3,树4,树5(也就是5个物品)。然后他从树1开始找,树1就沿自己的根到另一个子树(其他剩下的树中的树2开始),再从子树(树2)的根到 它的子树(树3),沿着根一直往下累加物品的价值sum...... ,当沿着根一直向下走后不满足条件了,就将现在拥有的价值与最终价值ans比较,大于就更新ans,否则不更新。 当树1全部查找完了后,并且也对比出了树1所有路线中的某条最大价值后,就开始来到了树2,树2也同理这样找,并且得最大的价值,再到树3。。。。
这段代码如下:
void dfs(int x,int W, int V, int sum, int* ans, int w[], int v[], int p[],int maxW,int maxV) { sum = sum + p[x]; W = W + w[x]; V = V + v[x]; *ans=max(*ans, sum); if(W>=maxW || V>=maxV) { return; } for(int j=x+1;j<6;j++) { if(W+w[j]<=maxW && V+v[j]<=maxV) { dfs(j, W, V, sum, ans, w, v, p, maxW, maxV); } } }
3、以此类推到 树5找完后就可以的最终满足条件的最大价值
注意事项:
1、从哪个树开始,它的子树只需要从这棵树后面的树开始
如从树2开始,搜索它的子树就从树3开始(判断符不符合条件),而子树树3就从它的子树4开始(判断符不符合条件),子树树4就从它的子树5开始(判断符不符合条件)。这样就可以完成一次查找。
可以画出树状图,就很容易理解
参考代码:
#include<stdio.h> int max(int num1,int num2) { if (num1 > num2)return num1; return num2; } void dfs(int x,int W, int V, int sum, int* ans, int w[], int v[], int p[],int maxW,int maxV) { ////x为第几个物,W为到目前为止背包重量,V为到目前为止背包的体积 //sum为到目前为止背包的价值(不一定最大),ans记录最终的最大价值 //w存每个物品的重量,v存每个物品的体积,p存每个物品的价值 //maxW题目规定的最大重量 //maxV题目规定的最大体积 sum = sum + p[x]; W = W + w[x]; V = V + v[x]; *ans=max(*ans, sum); if(W>=maxW || V>=maxV) { return; } for(int j=x+1;j<6;j++)//本树的下一棵树开始 { if(W+w[j]<=maxW && V+v[j]<=maxV)//本树是否可以到下一棵树 { dfs(j, W, V, sum, ans, w, v, p, maxW, maxV);//传入本树到目前为止的信息 } } } void test87() { int ans = 0; int w[6] = { 0 }; int v[6] = { 0 }; int p[6] = { 0 }; int sum = 0; int maxW = 0; int W = 0; int maxV = 0; int V = 0; scanf("%d %d", &maxV, &maxW); for(int i=1;i<6;i++) { scanf("%d %d %d", &p[i], &v[i], &w[i]); } dfs(0,W, V, 0, &ans, w, v, p,maxW,maxV); printf("%d", ans); } int main() { test87(); return 0; }
0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复