题目描述 Description
有n个砝码,现在要称一个质量为m的物体,请问最少需要挑出几个砝码来称?
注意一个砝码最多只能挑一次
输入描述 Input Description
第一行两个整数n和m,接下来n行每行一个整数表示每个砝码的重量。
输出描述 Output Description
输出选择的砝码的总数k,你的程序必须使得k尽量的小。
样例输入 Sample Input
3 10
5
9
1
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
1<=n<=30,1<=m<=2^31,1<=每个砝码的质量<=2^30
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define maxn 31 int n,ans=0x7fffffff; long long a[maxn],s[maxn],m; bool cmp(int x,int y){return x>y;} long long qread(){ long long i=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();} return i; } void dfs(int pos,int cnt,long long sum){ if(sum==m){ans=min(ans,cnt);return;} if(cnt>=ans)return; if(pos>n)return; for(int i=pos;i<=n;i++){ if(s[i]<m-sum)return; if(a[i]>m-sum)continue; dfs(i+1,cnt+1,sum+a[i]); } } int main(){ freopen("Cola.txt","r",stdin); scanf("%d",&n); m=qread(); for(int i=1;i<=n;i++)a[i]=qread(); sort(a+1,a+n+1,cmp); for(int i=n;i>=1;i--)s[i]=s[i+1]+a[i]; dfs(1,0,0); printf("%d",ans); }
#include<iostream> #include<cstdio> #include<algorithm> #include<map> using namespace std; int ans(1000),w[50],n; long long mm; map<int, int>m; void dfs(int js,int last,int sum,bool k) { int r=n; if(k){m[sum]=js;r/=2;} else { if(m.find(mm - sum)!=m.end()) ans=min(ans,js+m[mm-sum]); } for(int i=last;i<r;i++) dfs(js+1,i+1,sum+w[i],k); } int main() { scanf("%d%lld",&n,&mm); for(int i=0;i<n;i++) scanf("%d",&w[i]); dfs(0,0,0,true); dfs(0,n/2,0,false); printf("%d ",ans); return 0; }