LuoguP1441 砝码称重 解题报告【搜索+背包型DP】
2017-10-25 20:03
330 查看
题目描述
现有n个砝码,重量分别为a1,a2,a3,……,an,在去掉m个砝码后,问最多能称量出多少不同的重量(不包括0)。
输入输出格式
输入格式:
输入文件weight.in的第1行为有两个整数n和m,用空格分隔
第2行有n个正整数a1,a2,a3,……,an,表示每个砝码的重量。
输出格式:
输出文件weight.out仅包括1个整数,为最多能称量出的重量。
输入输出样例
输入样例#1:
3 1
1 2 2
输出样例#1:
3
说明
【样例说明】
在去掉一个重量为2的砝码后,能称量出1,2,3共3种重量。
【数据规模】
对于20%的数据,m=0;
对于50%的数据,m≤1;
对于50%的数据,n≤10;
对于100%的数据,n≤20,m≤4,m<n,ai≤100。
解题报告
这道题我们要解决两个问题,一个是处理出去掉m个砝码有多少种方案,第二个是要在一个确定的方案上找出这个方案最多能称出多少重量不同的物品,也就是砝码组合起来有多少种重量不同的情况。
对于第一个问题,我们采用搜索的方法解决,我们的dfs有两个参数,分别是当前搜索到的位置(u)和已经去掉的砝码个数(step)。
有两个显然的终止条件,一个是step>m,另一个是u=n+1(u的初始值为1)。
一个搜索到的点u,他的下一个状态(u+1)有去掉它和不去掉它两种选项,由此我们就要分别写两个dfs分开搜索。
对于第二个问题,我们采用背包问题的解法来解决。也就是开一个dp[j],表示砝码重量总计为i时的方案是否可行。显然,dp[j]从dp[j−a[i]]转移过来。
这样一来,剩下的就很明朗了:
现有n个砝码,重量分别为a1,a2,a3,……,an,在去掉m个砝码后,问最多能称量出多少不同的重量(不包括0)。
输入输出格式
输入格式:
输入文件weight.in的第1行为有两个整数n和m,用空格分隔
第2行有n个正整数a1,a2,a3,……,an,表示每个砝码的重量。
输出格式:
输出文件weight.out仅包括1个整数,为最多能称量出的重量。
输入输出样例
输入样例#1:
3 1
1 2 2
输出样例#1:
3
说明
【样例说明】
在去掉一个重量为2的砝码后,能称量出1,2,3共3种重量。
【数据规模】
对于20%的数据,m=0;
对于50%的数据,m≤1;
对于50%的数据,n≤10;
对于100%的数据,n≤20,m≤4,m<n,ai≤100。
解题报告
这道题我们要解决两个问题,一个是处理出去掉m个砝码有多少种方案,第二个是要在一个确定的方案上找出这个方案最多能称出多少重量不同的物品,也就是砝码组合起来有多少种重量不同的情况。
对于第一个问题,我们采用搜索的方法解决,我们的dfs有两个参数,分别是当前搜索到的位置(u)和已经去掉的砝码个数(step)。
有两个显然的终止条件,一个是step>m,另一个是u=n+1(u的初始值为1)。
一个搜索到的点u,他的下一个状态(u+1)有去掉它和不去掉它两种选项,由此我们就要分别写两个dfs分开搜索。
对于第二个问题,我们采用背包问题的解法来解决。也就是开一个dp[j],表示砝码重量总计为i时的方案是否可行。显然,dp[j]从dp[j−a[i]]转移过来。
这样一来,剩下的就很明朗了:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=20,M=2000; int n,m,a[N+5],vmax,ans; bool dp[M+5],flag[N+5]; void dfs(int u,int step) { if(step>m)return ; if(u==n+1) { if(step==m) { int tot=0; for(int i=1;i<=vmax;i++)dp[i]=false; for(int i=1;i<=n;i++) { if(flag[i])continue; for(int j=vmax;j>=a[i];j--) if(dp[j-a[i]])dp[j]=true; } for(int i=1;i<=vmax;i++)if(dp[i])tot++; ans=max(ans,tot); } return ; } dfs(u+1,step); flag[u]=1; dfs(u+1,step+1); flag[u]=0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]),vmax+=a[i]; dp[0]=true; dfs(1,0); printf("%d",ans); return 0; }
相关文章推荐
- 洛谷 1441 砝码称重 搜索+DP 解题报告
- LuoguP1941[NOIP2014] 飞扬的小鸟 解题报告【背包型DP】
- LuoguP2679[NOIP2015] 子串 解题报告【多维DP】
- 蓝桥杯 砝码称重 递归 解题报告
- LuoguP1131[ZJOI2007] 时态同步 解题报告【树形DP(?)】
- luoguP1441 【砝码称重】
- CodeVS1052 地鼠游戏 解题报告【背包型DP】
- LuoguP1351[NOIP2014] 联合权值 解题报告【树形DP】
- 砝码称重 解题报告
- LuoguP1074[NOIP2009] 靶形数独 解题报告【搜索】
- POJ 1702 解题报告——Eva's Balance:用砝码为物体称重
- CodeVS1025 选菜 解题报告【背包型DP】
- LuoguP1052[NOIP2005] 过河 解题报告【离散化+背包型DP】
- BZOJ 5072 [Lydsy 十月月赛] 树DP 解题报告
- [dp]POJ 3176 Cow Bowling解题报告
- 【解题报告】uva562_Dividing coins(划分硬币, dp, 01背包)
- HDU 4734 数位DP 解题报告
- 搜索专题解题报告
- codevs 1047 邮票面值设计 DFS+DP 解题报告
- hdu 4740 The Donkey of Gui Zhou dfs 搜索 解题报告