中南林業大學11th I 01揹包 二分

2021-08-20 04:45:43 字數 1383 閱讀 9919

01揹包是是乙個普通的動態規劃入門問題:

一共有n個物品, 第i個物品的體積為v[i];

有乙個揹包容量為m,現在我要挑選一些物品放入這個揹包

我現在知道在總體積不超過揹包容量的情況下,他一共有多少種放法(總體積為0也算一種放法)。

1 <= n <= 30, 1 <= m , v[i]<= 1e9

這就是乙個很簡單的01揹包問題,我可以告訴你核心**怎麼寫:

很簡單吧,但是……,你試一試吧。

輸入有多組,每一組第一行是n和m

接下來第二行到第n+1行,第i+1行表示v[i]。

輸出每個樣例的方案數,每個答案佔據一行。
示例1

3 1012

4

8
解析:

#include using namespace std;

typedef long long ll;

int main()

ll ans = 0;

for (int i = 0; i < (1 << n); i++)

cout << ans << endl;

}return 0;

}

但是n的大小為30,列舉子集的話也是會超時的 (2 ^ 30) 可是接近 1e9 的數量級別

首先我們將前 n/2 個物品進行子集的列舉,將其所有能達到重量量放入陣列中arr中

非遞減排序後,我們再列舉剩下 n - n/2個物品的子集.

對於每乙個子集計算其放入的重量和sum.用總容量w - sum.

得到我們還能放入多少重量的物品 res = w - sum

於是我們去前 n / 2個物品的子集和陣列 arr 中二分尋找

最後乙個小於等於 res 的元素的位置 pos (可用upper_bound求解).

於是[0,pos] <= res 這些都是可滿足條件的解,累加即可.

**:

#includeusing namespace std;

typedef long long ll;

vectorarr;

ll val[35];

int main()

{ int n;ll m;

while(~scanf("%d%lld",&n,&m))

{arr.clear();

for(int i=0;i>1,n2 = n - (n>>1);

//printf("%d %d\n",n1,n2);

for(int i=0;i

中南林業大學第十一屆程式設計競賽

theme 有很多砝碼,質量為w的0次方 1次方 n次方,每個砝碼都只有乙個。有乙個天平,給定乙個重物重量為m,問能否通過放置重物和砝碼使得天平平衡,重物和砝碼可以放在一邊或兩邊。2 w 10 9,1 m 10 9 solution 如果砝碼只能放在一邊,則若m w i,或1 w 0 w 1.w i...

東北林業大學OJ題目1

百步穿楊 problem 796 time limit 1000ms memory limit 65536k description 時維九月,序屬三秋,遼軍大舉進攻帽兒山,戰場上兩軍正交鋒.遼軍統帥是名噪一時的耶律洪豬,而帽兒山方則是派出了傳統武將 松樹葉子。雙方經過協商,約定在十一月八日正午十分...

A喝酒 北京林業大學校賽

王大釘喜歡喝酒,存貨都喝完了,他就去樓下買,正好樓下的商店為了響應學校的 acm 校賽推出了優惠活動 凡是在本店買的啤酒,喝完以後 3 3 個空瓶可以換一瓶,4 4 個瓶蓋也可以換一瓶酒。王大釘覺得太合算了,決定多買,現在他手裡的錢可以買 n n 瓶酒,但是他算不出來,通過活動兌換他一共可以喝到多少...