(DP003)背包与dfs综合 以洛谷P1441、P1474、P2347为例

一、流程

P1474和P2347可以看做是P1441的子问题,所以先分析P1441,拆解出子问题之后再看P1474和P2347,然后回头解决P1441.

二、P1441砝码称重

基本思路就是先dfs求出组合,联系前面做过的洛谷P1103书本整理,可以把去掉m个砝码转化为选择n-m个砝码,这样比较好想。求出组合之后,再用背包计算方案数。先是写出求组合的代码,这个比较基础:

void dfs(int cur,int lst){
                     //当前在选第cur个,上次选的是第lst个 
	if(cur>n-m){
   
		dp();
		//for(int i=1;i<=n-m;i++) cout<<path[i]<<' ';//一般输出路径检查一下 
		//cout<<endl;
		return;
	}
	if(n-lst<n-m-cur) return;                 //不够选的时候,剪枝 
	for(int i=lst+1;i<=n;i++){
   
		path[cur]=a[i];
		dfs(cur+1,i);
		path[cur]=0;                            //回溯 
	}
}

在主函数中执行dfs(1,0)即可,每次选择的组合保存在path里,然后每个组合生成完毕之后,执行一次dp,计算方案数与ans比较,找出最大的存在ans里,最后输出ans即可。
现在面临的就是如何计算方案数,本题的方案数不固定总和的方案,也就是砝码总重是不受约束的。我们先从算固定总和的方案数开始:

三、固定总和的方案数 P1474货币系统

可以把P1474的货币看作砝码,但是P1474是固定总和的,代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=100005;    
ll dp[maxn];
int wm;
int n;
int w[maxn];
int main(){
   
	
	scanf("%d%d",&n,&wm);
	for(int i=1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值