1. 程式人生 > >Codevs_P2144 砝碼稱重 2

Codevs_P2144 砝碼稱重 2

時間限制: 1 s
空間限制: 16000 KB
題目等級 : 鑽石 Diamond

題目描述 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

思路分析:對前面n/2個數生成所有可能的組合得到數集合A,以及得到這些數的最少需要的砝碼個數,map或者hashmap存起來,我用的stl的map就行

然後對後面n/2數同樣處理,得到集合B以及生成B中每個數至少需要的砝碼。

然後對前面得到的所有的數a∈A,遍歷是否M-a是否在B中,然後取前後兩部分生成a b最少需要砝碼個數的和中最小的

對於如何得到前面後面n/2個數生成所有可能的組合得到數集合,可以先得到一個數組合得到的所有數,然後在此基礎上得到兩個數組合得到的所有數,再再次基礎上得到三個數能夠組和的所有數。為了防止一個數被用兩次,可以記錄得到這些數的最大下標

#include<iostream>
#include<cstdio> #include<algorithm> #include<map> using namespace std; int main() { int n,m,a[33],i,j,ans=1000000007; map<int,int>mm; cin>>n>>m; for(i=0;i<n;i++) cin>>a[i]; for(i=1;i<(1<<(int)(n/2+1));i++) { int sum=0
,cnt=0; for(j=0;j<n/2;j++) if(i&(1<<j)) sum+=a[j],cnt++; if(!mm[sum]||cnt<mm[sum]) mm[sum]=cnt; } if(mm[m]) ans=mm[m]; for(i=1;i<(1<<(int)((n+1)/2+1));i++) { int sum=0,cnt=0; for(j=0;j<(n+1)/2;j++) if(i&(1<<j)) sum+=a[j+n/2],cnt++; if(sum==m) ans=min(ans,cnt); if(mm[m-sum]) ans=min(ans,mm[m-sum]+cnt); } cout<<ans<<endl; return 0; }

相關推薦

Codevs_P2144 砝碼 2

時間限制: 1 s 空間限制: 16000 KB 題目等級 : 鑽石 Diamond 題目描述 Description 有n個砝碼,現在要稱一個質量為m的物體,請問最少需要挑出幾個砝碼來稱? 注意一個砝碼最多隻能挑一次 輸入描述 Input De

2144 砝碼 2 用map離散化hasi+二分搜尋

2144 砝碼稱重 2  時間限制: 1 s  空間限制: 16000 KB  題目等級 : 鑽石 Diamond 題解 題目描述 Descrip

wikioi-天梯-提高一等-雜湊表-2144:砝碼2

題目描述 Description 有n個砝碼,現在要稱一個質量為m的物體,請問最少需要挑出幾個砝碼來稱? 注意一個砝碼最多隻能挑一次 輸入描述 Input Description 第一行兩個整數n和m,接下來n行每行一個整數表示每個砝碼的重量。

CODE【VS】2144 砝碼2(dfs+剪枝)

題目描述 Description 有n個砝碼,現在要稱一個質量為m的物體,請問最少需要挑出幾個砝碼來稱? 注意一個砝碼最多隻能挑一次 輸入描述 Input Description 第

砝碼2

題目描述 Description 有n個砝碼,現在要稱一個質量為m的物體,請問最少需要挑出幾個砝碼來稱? 注意一個砝碼最多隻能挑一次 輸入描述 Input Description 第一行兩個整數

CODEVS 2144 砝碼2

//二分dfs,最後合併 #include<bits/stdc++.h> using namespace std; const int maxn = 400000; int n, m,

wikioi 2144 砝碼 2 STL_map

看似dp,但是資料太大,不過n很小,可以暴力解決。 由於30個數組合情況太多,所以可以分成兩邊,首先預處理前n/2個數能組成哪些數,並且最小消耗多少砝碼,map儲存下來。 然後處理右邊能組合成什麼數,相加就夠了。 注意這樣會漏掉兩種情況,就是光一邊就能組成最終答案的(因為m

NOI題庫--砝碼V2(多重揹包2^n拆分)

以前只會寫多重揹包的原版,渣的不行,為了做此題不得不學習了一下,發現其實也不難,只要理解了方法就好多了(PS:其實和倍增挺像的) 8756:砝碼稱重V2 總時間限制: 1000ms 記憶體限制:

51nod 1837 砝碼【數學,規律】

可能 blank sed gif span nbsp sin pro n-1 題目鏈接:51nod 1837 砝碼稱重 小 Q 有 n 個砝碼,它們的質量分別為 1 克、 2 克、……、 n 克。 他給 i 克的砝碼標上了編號 i (i =

luogu1441 砝碼

true down size mark std ios post pos tdi 搜索+背包就是了 #include <iostream> #include <cstring> #include <cstdio> using namesp

P1441 砝碼

ron 思路 sca 去掉 class sample ret eof 不同的 題目描述 現有n個砝碼,重量分別為a1,a2,a3,……,an,在去掉m個砝碼後,問最多能稱量出多少不同的重量(不包括0)。 輸入輸出格式 輸入格式: 輸入文件weight.in的第1行為有兩

P2347 砝碼 (01背包)

格式 sub base col can span %d spa 輸出 題目描述 設有 1g1g1g 、 2g2g2g 、 3g3g3g 、 5g5g5g 、 10g10g10g 、 20g20g20g 的砝碼各若幹枚(其總重 ≤1000 \le 1000≤1000 ), 輸

洛谷P2347 砝碼

getc org www. ogr ext get tle ati pro 題目 貌似是某年提高組簽到題,六重循環零壓力AC,差點怒踩std 但本蒟蒻決定寫正解——多重背包,果斷20分 原因是寫錯了狀態轉移方程。。。神才知道我咋過的樣例和兩個測試點 扯遠了 多重

洛谷P1411 砝碼

false http 時間 .org 背包 ret code 就是 傳送門 傳送門啦 這個題總體思路就是先搜索在 $ dp $ void dfs(int keep,int now){ //使用 放棄 if(now > m) return;

【練習】砝碼

 P1441 砝碼稱重 思路:dfs列舉去掉哪些砝碼, 01揹包求方案數, 各種情況取max記為ans輸出√ 邊界情況處理不好交了三遍QAQ dp[j] = dp[j] + dp[j - a[i]] 選上這個砝碼的情況+ 不選的情況 1 #include<cstdio>

[P1441]砝碼 (搜尋+DP)

對於我這種蒟蒻,是很不錯的一題了。 dfs搜尋當前狀態 滿足時DP 比較坑的地方就是起始的地方 我一開始從1開始,搜尋寫的是從0開始。 後來就統一用0開始的了。 #include<bits/stdc++.h> #define max(a,b) (a>b?a:b) usi

洛谷1441 砝碼

原題連結 挺水的一道題。 \(DFS\)列舉被刪除的砝碼,每次刪完後進行\(01\)揹包計數,取最大值即可。 這題不需要剪枝即可通過。 我這裡是用連結串列儲存的資料。 #include<cstdio> #include<cstring> #include<algorithm&

洛谷P1441 砝碼(加強版)

題目連結 P1441 砝碼稱重 解題思路: 搜尋/列舉+dp dp過程參考弱化版的P2347 砝碼稱重。 妙啊,真的是妙啊… 感覺這題搜尋和dp結合的恰到好處。利用dfs先枚舉出所有可能的情況,當陣列

1449 砝碼 1 秒 (貪心)

1449 砝碼稱重 1 秒 131,072 KB 40 分 4 級題 現在有好多種砝碼,他們的重量是 w0,w1,w2,... 每種各一個。問用這些砝碼能不能表示一個重量為m的東西。 樣例解釋:可以將重物和3放到一個托盤中,9和1放到另外一個托盤中。 思路: w進位制演算法, 如果沒有天平,只是這些砝碼

題解 P1441 【砝碼

題目描述 現有n個砝碼,重量分別為a1,a2,a3,……,an,在去掉m個砝碼後,問最多能稱量出多少不同的重量(不包括0)。 【資料規模】 對於20%的資料,m=0; 對於50%的資料,m≤1; 對於50%的資料,n≤10; 對於100%的資料,n≤20,m≤4,m<n,ai≤100。 主要思路