wikioi 2144 砝碼稱重 2 STL_map
阿新 • • 發佈:2019-02-06
看似dp,但是資料太大,不過n很小,可以暴力解決。
由於30個數組合情況太多,所以可以分成兩邊,首先預處理前n/2個數能組成哪些數,並且最小消耗多少砝碼,map儲存下來。
然後處理右邊能組合成什麼數,相加就夠了。
注意這樣會漏掉兩種情況,就是光一邊就能組成最終答案的(因為map沒有存數也是0),特殊處理一下就行。
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <map> #define inf 0x3f3f3f3f using namespace std; int a[50]; int main() { int n,m,i,j; scanf("%d%d",&n,&m); map<int,int> mp; for(i=1;i<=n/2;i++) { scanf("%d",&a[i]); } int top=(1<<(i-1)); for(j=1;j<top;j++) { int tmp=j; int k=1; int sum=0; int tot=0; while(tmp) { if(tmp&1) {sum+=a[k];tot++;} tmp>>=1; k++; } if(!mp[sum]||tot<mp[sum]) mp[sum]=tot; } int ans=mp[m]?mp[m]:inf; for(i=n/2+1,j=1;i<=n;i++,j++) { scanf("%d",&a[j]); } top=(1<<(j-1)); for(int j=1;j<top;j++) { int tmp=j; int k=1; int sum=0; int tot=0; while(tmp) { if(tmp&1) {sum+=a[k];tot++;} tmp>>=1; k++; } if(sum==m) ans=min(ans,tot); if(mp[m-sum]==0) continue; ans=min(ans,tot+mp[m-sum]); } printf("%d\n",ans); return 0; }