砝码称重2
【題目描述】
有n個砝碼,現要稱一個質量為m的物體,詢問最少需要挑出幾個砝碼來稱,一個砝碼最多只能挑一次。
【輸入描述】第一行輸入兩個整數n和m;
接下來n行,每行輸入一個整數表示砝碼的重量。
【輸出描述】輸出一個整數表示最少需要的砝碼數。
【樣例輸入】3 10
5
9
1
【樣例輸出】2
【數據范圍及提示】
1 <= n <= 30,1 <= m <= 231,1 <= 每個砝碼的質量 <= 230。
源代碼:#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int m,n,L1=1,L2=1,Min=1000000000,i[31]; struct Node {int Sum,Weight; }F1[400000],F2[400000]; //計算好情況數目,別想當然。 int Rule(Node t1,Node t2) {return t1.Weight<t2.Weight; } void DFS1(int t,int S,int W) //t代表當前砝碼編號,S代表已使用的砝碼數量,W代表已使用的砝碼總重。 {if (t>(n>>1))return;F1[++L1].Sum=S+1;F1[L1].Weight=W+i[t];DFS1(t+1,S+1,W+i[t]); //取還是不取。DFS1(t+1,S,W); } void DFS2(int t,int S,int W) //同理于上。 {if (t>n)return;F2[++L2].Sum=S+1;F2[L2].Weight=W+i[t];DFS2(t+1,S+1,W+i[t]);DFS2(t+1,S,W); } int Find(int t) //排序之后,二分查找。 {int Left=0,Right=L2,Mid=L2>>1;while (Left<=Right){if (F2[Mid].Weight>t){Right=Mid-1;Mid=(Left+Right)>>1;}if (F2[Mid].Weight<t){Left=Mid+1;Mid=(Left+Right)>>1;}if (F2[Mid].Weight==t)return Mid;}return -1; } int main() //然而并沒有用到Hash。 {scanf("%d%d",&n,&m);for (int a=1;a<=n;a++)scanf("%d",&i[a]);sort(i+1,i+n+1);DFS1(1,0,0);sort(F1+1,F1+L1+1,Rule);DFS2((n>>1)+1,0,0);sort(F2+1,F2+L2+1,Rule);for (int a=1;a<=L1;a++){int t=Find(m-F1[a].Weight);if (t!=-1) //符合條件。Min=min(Min,F1[a].Sum+F2[t].Sum);}printf("%d",Min);return 0; }/*解題思路:本質上就是定義一個左根堆和一個右根堆,這樣可以節省很多空間。之所以排序,是為了保證二分的正確性,然后進行查找匹配。 */轉載于:https://www.cnblogs.com/Ackermann/p/5903333.html
總結
- 上一篇: solr 的 field, copyfi
- 下一篇: 06_使用开源项目提交参数