wikioi-天梯-提高一等-雜湊表-2144:砝碼稱重2
題目描述 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
型別:其他 難度:2
題意:給出n個數,要求從中挑出k個數,使它們的和為m,求最小的k
分析:一個簡單的思路:
1、就是把n個數分成兩份,分別求每份的數所有可能取的和,用cnt1和cnt2兩個雜湊表記錄,其中cnt1[i]=j表示最少需要湊出和為i,至少需要j個數。
遍歷方法可以用二進位制表示每個數是否取,比如有5個數,那麼遍歷1 - (2^5-1),每個數二進位制為1,則將這個數累加,將累加的和作為雜湊表的key,選取的個數作為雜湊表的value,若比之前的小或是新出現的則更新雜湊表對應項
2、對於兩個雜湊表cnt1和cnt2,遍歷其中一個雜湊表,設當前遍歷的項為cnt1[i]=j,那麼找cnt2[m-i]=k是否存在,若存在,那麼j+k即為總共需要取的個數,記錄最小值即為所求
3、最後分別看cnt1[m]和cnt2[m]是否存在,就是單獨取兩部分的和就能構成結果,更新結果為最小值
用stl map實現雜湊的功能,比自己寫雜湊稍微慢了點,不過夠用了。
本來嘗試用stl hash_map實現,但是hash_map不是ansi c的標準,我用的編譯器要加using namespace __gnu_cxx,並且wikioi的編譯器不認,就沒有用。
程式碼:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<algorithm> #include<vector> using namespace std; map<long long,int> cnt1,cnt2; int main() { int n; long long m; vector<int> da; scanf("%d%lld",&n,&m); for(int i=0; i<n; i++) { int tmp; scanf("%d",&tmp); da.push_back(tmp); } sort(da.begin(),da.end()); int l1 = da.size()/2; int l2 = da.size() - l1; for(int i=1; i<1<<l1; i++) { long long sum=0; int tc = 0; for(int j=i,k=0; j; j>>=1,k++) if(j&1) { sum += (long long)da[k]; tc++; } int now = cnt1[sum]; if(!now || tc<now) cnt1[sum] = tc; } for(int i=1; i<1<<l2; i++) { long long sum=0; int tc = 0; for(int j=i,k=l1; j; j>>=1,k++) if(j&1) { sum += (long long)da[k]; tc++; } int now = cnt2[sum]; if(!now || tc<now) cnt2[sum] = tc; } int ans = 50; map<long long,int>::iterator it; for(it=cnt1.begin(); it!= cnt1.end(); it++) { long long left = m-it->first; int tmp = it->second; if(left > 0) { int tmp2 = cnt2[left]; if(tmp2) { tmp += tmp2; ans = min(ans,tmp); } } } int r1 = cnt1[m]; int r2 = cnt2[m]; if(r1) ans = min(ans,r1); if(r2) ans = min(ans,r2); printf("%d\n",ans); }
相關推薦
wikioi-天梯-提高一等-雜湊表-2144:砝碼稱重2
題目描述 Description 有n個砝碼,現在要稱一個質量為m的物體,請問最少需要挑出幾個砝碼來稱? 注意一個砝碼最多隻能挑一次 輸入描述 Input Description 第一行兩個整數n和m,接下來n行每行一個整數表示每個砝碼的重量。
wikioi-天梯-提高一等-高精度普及-3118:高精度練習之除法
題目描述 Description 給出兩個正整數A和B,計算A/B整數部分的值。保證A和B的位數不超過500位。 輸入描述 Input Description 讀入兩個用空格隔開的正整數 輸出描述 Output Description 輸出
雜湊表Hash:概念與基本操作
什麼是Hash Hash就像是一個桶排,那隻不過是把各個元素的數值當做下標進行儲存.其最常用的用途就是用來判重.但是,如何對字串進行判重,不可能一個一個往前超,若n上萬則顯然不可行.我們可以選擇進行Hash,將每一個字串或者大數字進行一定的操作即可進行. 對大整數型別進行Hash 取模法 對於每一個
wikioi 2144 砝碼稱重 2 STL_map
看似dp,但是資料太大,不過n很小,可以暴力解決。 由於30個數組合情況太多,所以可以分成兩邊,首先預處理前n/2個數能組成哪些數,並且最小消耗多少砝碼,map儲存下來。 然後處理右邊能組合成什麼數,相加就夠了。 注意這樣會漏掉兩種情況,就是光一邊就能組成最終答案的(因為m
2144 砝碼稱重 2 用map離散化hasi+二分搜尋
2144 砝碼稱重 2 時間限制: 1 s 空間限制: 16000 KB 題目等級 : 鑽石 Diamond 題解 題目描述 Descrip
CODE【VS】2144 砝碼稱重2(dfs+剪枝)
題目描述 Description 有n個砝碼,現在要稱一個質量為m的物體,請問最少需要挑出幾個砝碼來稱? 注意一個砝碼最多隻能挑一次 輸入描述 Input Description 第
CODEVS 2144 砝碼稱重2
//二分dfs,最後合併 #include<bits/stdc++.h> using namespace std; const int maxn = 400000; int n, m,
Hash(雜湊/雜湊)表中衝突處理及命中計算
前言 本片部落格主要講的是雜湊表中簡單的衝突處理的方法,以及命中率計算。原理方面基本沒有講解,基本就講個方法,主要用於知識記錄以及幫助一些刷題玩家瀏覽。 簡而言之,不講技術,只講方法。 引言 寫這篇部落格的契機是在刷pat甲級題遇到了一道寫雜湊的題目,結果英文太次被欺負了。之後靠翻譯讀懂題
查詢演算法 淺談演算法和資料結構: 七 二叉查詢樹 淺談演算法和資料結構: 十一 雜湊表
閱讀目錄 1. 順序查詢 2. 二分查詢 3. 插值查詢 4. 斐波那契查詢 5. 樹表查詢 6. 分塊查詢 7. 雜湊查詢 查詢是在大量的資訊中尋找一個特定的資訊元素,在計算機應用中,查詢是常用的基本運算,例如編譯程式中符號表的查詢。本文
【LeetCode】雜湊表 hashmap(共88題)
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } 【1】Two Sum 【3】Longest Substring Without Repeating Characters 【18】4Sum
記錄一下雜湊表底層原理
理解HashMap底層,首先應該理解Hash函式 從解決一個問題入手:大量的資料要儲存查詢,構造雜湊表來解決 初步想法 借鑑陣列下標訪問的思路來做,只需知道起始位置和下標值, 不管陣列中有多少個元素,都可以一次訪問到, 將元素和元素位置建立一種一一對應的關係 Hash函式的出現 輸入的元素的範圍
散列表(雜湊表)+雜湊衝突的解決方法
轉載http://www.nowamagic.net/academy/detail/3008060 1散列表 1簡單來說就是給一個key,就可以找到對應的key的儲存位置,就像身份證對應一個人一樣 儲存位置 = f(key) 2hashMap的key就是用到散列表 1.1雜湊衝突
九章演算法筆記 8.雜湊表與堆 Hash & Heap
大綱 cs3k.com 資料結構概述 雜湊表 Hash: a.原理 b.應用 堆 Heap: a.原理 b.應用-優先佇列 Priority Queue c.替代品-TreeMap 資料結構的兩類問題 cs3k
27-集合--Set及其子類(HashSet+LinkedHashSet+TreeSet)+二叉樹+Comparable+Comparator+雜湊表+HashSet儲存自定義物件+判斷元素唯一的方式
一、Set 1、Set:元素不可以重複,是無序的(存入和取出的順序不一致) 2、Set介面中的方法和Collection中的方法一致 3、Set集合的元素取出方式只有一種:迭代器iterator() Set set = new HashSet(); I
基於雜湊表實現字典和集合
上一節說到了雜湊表。 我們提到了字典和集合是由雜湊表實現的,具體的實現過程是怎麼樣的呢? 其實很簡單,字典裡面有取值,新增值,正好對應的就是雜湊表中的find和add方法。使用__getitem__和__setitem__代替兩者就可以了。然後對於keys,values取值,只需要遍歷迴圈就行了。 這裡
雜湊表的原理及實現
雜湊表(Hash table,也叫散列表), 是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做散列表。 雜湊表hash table(key,value) 的做法
資料結構基礎之查詢(下):雜湊表
轉自:http://www.cnblogs.com/edisonchou/p/4706253.html 查詢(下):雜湊表 雜湊(雜湊)技術既是一種儲存方法,也是一種查詢方法。然而它與線性表、樹、圖等結構不同的是,前面幾種結構,資料元素之間都存在某種邏輯關係,可以用連線圖示
構建雜湊表——優化暴力求解方程
/* Consider equations having the following form: a*(x1)^2+b*(x2)^2+c*(x3)^2+d*(x4)^2=0 a, b, c, d are integers from the interval [-50,50] and
構造雜湊表——求前m大的數
Problem Description 給你n個整數,請按從大到小的順序輸出其中前m大的數。 Input 每組測試資料有兩行,第一行有兩個數n,m(0<n,m< 1000000),第二行包含n個各不相同, 且都處於區間[-500000,500
雜湊表—拉鍊法
public class Link { /** * 有序連結串列連結點 */ public int data; public Link nextLink; public Link(int data){ this.data = data; } publi