刷题记录-codevs2144 砝码称重 2

来源:互联网 发布:java程序开发步骤 编辑:程序博客网 时间:2024/05/01 06:25

典型的折半枚举法

本质上是用空间换时间的思想,把一半的数据搜过之后用数组保存起来,

搜另一半的时候就可以直接使用了

这样就可以把时间复杂度由乘转变为和

效率改善非常大哦

*************************************

#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>#include<map>#define MAXN 35using 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;}