problem description
有一天Feynman去书店买书,他有m元钱,书店里有n本书,每本书的价格为pi元。Feynman迫不及待地想把书买回家看,并把身上的钱全部花完来买书,记刚好买k本书。请帮Feynman计算他是否刚好能用m元买k本书。
Input
第一行输入三个整数m(1<=m<=100000000),n(1<=n<=30),k(1<=k<=min(8,n))
接下来一行输入n个整数,表示每本书的价格pi(1<=pi<=100000000)。
Output
如果Feynman刚好能用m元买k本书,输入一行“Yes”,否则输出"No"。
思路
利用DFS进行枚举(如果用二进制枚举可能因为数太大而进行不了,于是用递归思想,每一个元素选不选有两个分支用dfs进行搜索)
注意一些剪枝情况,另外将sum和num进行传参降低时间复杂度。
代码示例
#include<iostream>
using namespace std;
#define MAX 100
int s,n,m;
int arr[MAX];
int vis[MAX];//标记1
int flag;//标记2
void dfs(int a,int sum,int num)
{
if(a>n) return ; //a最大等于n
vis[a]=1;
if(num==m){
if(sum==s){
flag++;
return ;
}
else if(sum>s||sum<s) return ;
}
if(vis[a]==1){
num++;
sum+=arr[a];
dfs(a+1,sum,num);
sum-=arr[a];
num--;
vis[a]=0;//创造分支
}
if(vis[a]==0){
dfs(a+1,sum,num);
}
//cout<<num<<"(⊙o⊙)"<<endl;
}
int main()//这种方法是对每种元素有无从头枚举
{
cin>>s>>n>>m;
for(int i=0;i<n;++i){
cin>>arr[i];
vis[i]=0;
}
flag=0;
dfs(0,0,0);
if(flag>0) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}