典型的折半枚举法
本质上是用空间换时间的思想,把一半的数据搜过之后用数组保存起来,
搜另一半的时候就可以直接使用了
这样就可以把时间复杂度由乘转变为和
效率改善非常大哦
*************************************
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> #include<map> #define MAXN 35 using namespace std; int n,m; int a[MAXN]; int L,R; int ans=0x7fffffff; map<int,int> p; void dfs1(int k,int s,int c){ if(p.count(s)){ if(p[s]>=c){ p[s]=c; } } else{ p[s]=c; } for(int i=k;i<=L;i++){ if(s+a[i]<=m){ dfs1(i+1,s+a[i],c+1); } } } void dfs2(int k,int s,int c){ if(p.count(m-s)){ ans=min(ans,p[m-s]+c); } for(int i=k;i<=R;i++){ if(s+a[i]<=m){ dfs2(i+1,s+a[i],c+1); } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } sort(a+1,a+n+1); L=n/2; R=n; dfs1(1,0,0); dfs2(L+1,0,0); printf("%d",ans); return 0; }