POJ 3977 折半列舉

2022-07-23 08:09:17 字數 1174 閱讀 1622

給你n個數,n最大35,讓你從中選幾個數,不能選0個,使它們和的絕對值最小,如果有一樣的,取個數最小的 

子集個數共有2^n個,所以不能全部列舉,但是可以分為兩部分列舉;列舉一半的所有情況,然後後一半二分即可;

1 #include"

bits/stdc++.h"2

#define n 45

3using

namespace

std;

4 typedef long

long

ll;5

6intn;7

ll a[n];89

ll abs(ll x)

1013

14int

main()

1535

}36 ans = min(ans, make_pair(abs(sum), cnt));///

全部是前半部分的;

37if(m[sum])///

更新cnt為小的;

38 m[sum] =min(m[sum], cnt);

39else

40 m[sum] =cnt;41}

4243

for(int i=1; i<1

<<(n-n/2); i++)

4453

}54 ans = min(ans, make_pair(abs(sum), cnt));///

全部是後半部分的;

5556 it = m.lower_bound(-sum);///

找到第乙個大於-sum的位置,然後取兩種情況的最小值;

5758

if(it !=m.end())

59 ans = min(ans, make_pair(abs(sum+it->first), cnt+it->second));

60if(it !=m.begin())

6165

}66 printf("

%i64d %d\n

", ans.first, ans.second);67}

68return0;

69 }

POJ 3977 折半列舉

如無法區分折半列舉,二分,這裡 這題我感覺出了是用列舉,畢竟資料範圍很小,但是,集合中每個元素都有可能被選或者不被選,根據計數原理應該會有 2 1 種情況,需要刨除空集,列舉顯然是會t掉,那怎麼辦呢?考慮選出來的集合有幾種情況,有可能都在前一半,有可能都在後一半,還有可能前後都有,前後都有的情況可以...

poj 3977 折半列舉

題目大意 給定n n 35 個數字,每個數字都 2 15.其中乙個或多個數字加和可以得到s,求出s的絕對值的最小值,並給出當s取絕對值最小值時,需要加和的數字的個數。題目分析 實現 c include include include include include include includeus...

poj3977(折半列舉,多坑)

translation 給出一列數列,找出其中的非空連續子串行,使得其和的絕對值最小。如果有相同的和的情況下輸出元素個數最少的那個 solution 折半列舉即可 note 思路很簡單,分成兩半,折半列舉即可,但是 中有很多坑。首先必須對前後兩部分只選乙個的情況單獨考慮。然後如果 ans sum的預...