一、流程
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