bitset
构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int main () { bitset <4> bitset1; bitset <8> bitset2(12 ); string s = "100101" ; bitset <10> bitset3(s); string s2 = "100101" ; bitset <4> bitset4(s2); cout << bitset1 << endl ; cout << bitset2 << endl ; cout << bitset3 << endl ; cout << bitset4 << endl ; }
可用的操作符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 bitset <4> foo (string ("1001" ));bitset <4> bar (string ("0011" ));cout << (foo^=bar) << endl ; cout << (foo&=bar) << endl ; cout << (foo|=bar) << endl ; cout << (foo <<= 2 ) << endl ; cout << (foo >>= 1 ) << endl ; cout << (~bar) << endl ; cout << (bar << 1 ) << endl ; cout << (bar >> 1 ) << endl ; cout << (foo == bar) << endl ; cout << (foo != bar) << endl ; cout << (foo & bar) << endl ; cout << (foo | bar) << endl ; cout << (foo ^ bar) << endl ;
此外,还可以通过[]
来访问元素(类似数组),注意最低位下标为0
1 2 3 4 bitset <4> foo(string ("1011" ));cout << foo[0 ] << endl ; cout << foo[1 ] << endl ; cout << foo[2 ] << endl ;
可用函数
1 2 3 4 5 6 7 bitset <8> foo(string ("10011011" )); cout << foo.count() << endl ; cout << foo.size() << endl ; cout << foo.test(0 ) << endl ; cout << foo.any() << endl ; cout << foo.none() << endl ; cout << foo.all() << endl ;
1 2 3 4 5 6 7 8 bitset <8> foo(string ("10011011" ));cout << foo.flip(2 ) << endl ; cout << foo.flip() << endl ; cout << foo.set () << endl ; cout << foo.set (3 , 0 ) << endl ; cout << foo.set (3 ) << endl ; cout << foo.reset(4 ) << endl ; cout << foo.reset() << endl ;
类型转换
1 2 3 4 5 bitset <8> foo(string ("10011011" ));string s = foo.to_string();unsigned long a = foo.to_ulong(); cout << s << endl ;cout << a << endl ;
AOJ: Osenbei
有一个烤饼器可以烤r行c列的煎饼,煎饼可以正面朝上(用1表示)也可以背面朝上(用0表示)。一次可将同一行或同一列的煎饼全部翻转。现在需要把尽可能多的煎饼翻成正面朝上,问最多能使多少煎饼正面朝上?
输入:多组输入,每组第一行为二整数r, c (1 ≤ r ≤ 10, 1 ≤ c ≤ 10 000),剩下r行c列表示煎饼初始状态。r=c=0表示输入结束。
输出:对于每组输入,输出最多能使多少煎饼正面朝上。
测试数据:
1 2 3 4 5 6 7 8 9 10 11 输入: 2 5 0 1 0 1 0 1 0 0 0 1 输出:9 输入: 3 6 1 0 0 0 1 0 1 1 1 0 1 0 1 0 1 1 0 1 输出:15
思路:
先对行进行翻转,若有r行,一共要进行2 r 2^r 2 r 次,对于行翻转后的每一种情况,再进行列的翻转,列不需要真的翻转,只需要统计一下每一列是正面朝上还是反面朝上的煎饼多,取综合
对于这2 r 2^r 2 r 个综合,取最大的那个即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> #include <bitset> #include <algorithm> using namespace std ;bitset <10000> cookie[10 ];int main () { int r, c; while (cin >> r >> c && r) { int result = 0 ; for (int i = 0 ; i < r; i++) { for (int j = 0 ; j < c; j++) { bool what; cin >> what; cookie[i][j] = what; } } int permute = 1 << r; for (int k = 0 ; k < permute; k++) { for (int j = 0 ; j < r; j++) { if (k & (1 << j)) { cookie[j].flip(); } } int possible_num = 0 ; for (int j = 0 ;j < c; j++) { int up_number = 0 ; for (int i = 0 ; i < r; i++) { if (cookie[i][j]) { up_number++; } } possible_num += max(up_number, r - up_number); } result = max(result, possible_num); for (int j = 0 ; j < r; j++) { if (k & (1 << j)) { cookie[j].flip(); } } } cout << result << endl ; } return 0 ; }
POJ:Cleaning Shifts
题意:有n头牛,它们都有一个工作时间的区间s至e,给定一个总的工作时间t,问最少需要多少头牛才能覆盖从1到t的工作时间
思路:
简单的区间贪心 。首先将牛的工作时间按起始时间最小(第一优先级)、结束时间最大的顺序(第二优先级)进行排序,然后取第n头牛时,要满足一下条件:1、第n头牛的s要小于等于第n-1头牛的e+1(这里要注意题目里给的是时间点,不是区间段) 2、第n头牛的e尽可能的大。之后就得考虑一些特例情况就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <vector> #include <cstdio> #include <algorithm> using namespace std ;const int MAXN = 25005 ;int n, t;struct node { int s, e; }; node cows[MAXN]; bool comp (const node a, const node b) { if (a.s != b.s) { return a.s < b.s; } else { return a.e >= b.e; } } int solve (int ans) { if (n < 1 || cows[0 ].s != 1 ) { return -1 ; } if (n == 1 ) { if (cows[0 ].s == 1 && cows[0 ].e == t) { return 1 ; } else { return -1 ; } } int i = 1 , maxE = cows[0 ].e, maxNextE = cows[0 ].e; while (i < n) { if (maxE == t) { return ans; } bool flag = false ; if (cows[i].s <= maxE + 1 ) { while (i < n && cows[i].s <= maxE + 1 ) { if (cows[i].e > maxNextE) { maxNextE = cows[i].e; flag = true ; } i++; } if (flag) { maxE = maxNextE; ans++; } } else { return -1 ; } } if (maxE == t) { return ans; } else { return -1 ; } } int main () { while (scanf ("%d%d" , &n, &t) == 2 ) { for (int i = 0 ; i < n; i++) { scanf ("%d%d" , &cows[i].s, &cows[i].e); } sort(cows, cows + n, comp); printf ("%d\n" , solve(1 )); } return 0 ; }
区间贪心问题
选择不相交区间
描述
数轴上有n个开区间(ai, bi)
。选择尽量多个区间,使得这些区间亮亮没有公共点
思路
区间x
完全包含y
,选y
按照bi
从小到大排序,从第一个区间开始选
把所有和上一个区间相交的区间排除在外
贪心策略是:一定要选第一个区间(实际上就是活动安排问题)
区间选点问题
描述
数轴上有n个闭区间[ai, bi]
,取尽量少的点,使得每一个区间内都至少有一个点(不同区间内含的点可以是同一个)
思路
按bi
从小到大排序(b相同时,a从大到小排序)
区间包含的情况下,大区间不需要考虑
取最后一个点

区间覆盖问题
描述
数轴上有n个闭区间[ai, bi]
,选择尽量少的区间覆盖一条指定线段[s, t]
思路
POJ 1328: Radar Installation
大意:
给定一个直角坐标系,定义x轴为海岸线,海岸线上方是海,下方是陆地.
在海域零星分布一些海岛, 需要要在海岸线上安装若干个雷达覆盖这些海岛,
每个雷达的覆盖半径都是相同且固定的.
现在给定所有海岛的坐标(x,y), 以及雷达的覆盖半径d,
问可以覆盖所有海岛的最小雷达数.
思路:
如果出现任意一个海岛的y值大于d,即无解
在所有y值都小于d的时候,考虑每一个海岛的设置的雷达的边界(即预处理)
假设一个海岛的位置为(x, y)
,雷达半径为d
设雷达在海岸线上的左右边界为left, right
m = sqrt(d*d - y*y)
则left = x - m, right = x + m
然后针对上述所求的每一对(left, right)
按照left
进行排序,然后从左往右遍历,如果当前最右边的雷达不能覆盖当前海岛,则增加一个雷达,其位置为radio_x = x + m
,即安排在能观测到该海岛的最右侧位置,这样即可保证所需的雷达数目是最少的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #include <cstdio> #include <cmath> #include <algorithm> using namespace std ;struct node { double s, e; }; int n, d, k;node area[1010 ]; int cmp (node a, node b) { if (a.e == b.e) { return a.s > b.s; } return a.e < b.e; } int change (int x, int y, int k) { if (y > d) { return 0 ; } double a, b, m = sqrt (d * d - y * y); a = x - m; b = x + m; area[k].s = a; area[k].e = b; return 1 ; } int main () { int x, y, k = 0 ; while (scanf ("%d%d" , &n, &d) && (n || d)) { bool flag = false ; for (int i = 0 ; i < n; i++) { scanf ("%d%d" , &x, &y); if (!change(x, y, i)) { flag = true ; } } if (!flag) { sort(area, area + n, cmp); double x = area[0 ].e; int num = 1 ; for (int i = 1 ; i < n; i++) { if (area[i].s > x) { num++; x = area[i].e; } } printf ("Case %d: %d\n" , k + 1 , num); } else { printf ("Case %d: -1\n" , k + 1 ); } k++; } }
PS:这里最重要的是预处理工作,我这个zz,在设x的时候,double x
写成了int x
,然后就一直没过…无语了
POJ 3190: Stall Reservations
大意:每头奶牛拥有自己的可以挤奶的时间。且每头牛都必须挤奶,而他们又不愿意在一间房,问最少需要造多少间房。
思路:
可以用贪心做,依据开始时间排序。依次放奶牛(开始时间最小),若所有房间都没空,那么就再造一间房。
判断房间状态,用for循环会超时 ,可以使用优先队列,队列排序是房间空的越早越排前。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #include <cstdio> #include <algorithm> #include <queue> using namespace std ;const int N = 50010 ;int n;struct node { int s, e; int stall; int tag; }; struct RNode { int first; int second; bool operator < (const RNode &a) const { if (first == a.first) { return second > a.second; } return first > a.first; } }; priority_queue<int , vector <RNode> >q; bool cmp (const node a, const node b) { if (a.s == b.s) { return a.e < b.e; } return a.s < b.s; } node cows[N]; int solve (int n) { int maxH = 1 ; cows[1 ].stall = 1 ; RNode node; node.first = cows[1 ].e; node.second = maxH; q.push(node); for (int i = 2 ; i <= n; i++) { if (cows[i].s <= q.top().first) { maxH++; RNode node; node.first = cows[i].e; node.second = maxH; q.push(node); cows[i].stall = maxH; } else { int house = q.top().second; cows[i].stall = house; q.pop(); RNode node; node.first = cows[i].e; node.second = house; q.push(node); } } return maxH; } int main () { while (scanf ("%d" , &n) != EOF) { int res[n]; for (int i = 1 ;i <= n; i++) { scanf ("%d%d" , &cows[i].s, &cows[i].e); cows[i].tag = i; } sort(cows + 1 , cows + n + 1 , cmp); int maxH = solve(n); printf ("%d\n" , maxH); for (int i = 1 ; i <= n; i++) { res[cows[i].tag] = cows[i].stall; } for (int i = 1 ; i <= n; i++) { printf ("%d\n" ,res[i]); } while (!q.empty()) { q.pop(); } } }
大致思路:先按照起始时间对奶牛进行排序,这里需要注意因为疏忽的时候是按照原来奶牛的顺序,所以需要记录下奶牛的编号,即使在排序之后也依然能够按照顺序输出
然后创建一个优先队列,按照结束时间创建的一个小根堆,每次给一头奶牛安排stall的时候,就先判断小根堆的top()
的时间是否小于当前奶牛的起始时间,如果小于,则说明该房间已经空出来了,可以安排该奶牛,如果大于,则表明当前所有的stash
都已经满了,需要重新建造一个stash来放这头奶牛。
最后按照编号顺序输出他们的stash号码。
优先队列(priority_queue)
基本操作
1 2 3 4 5 6 7 top empty size push emplace pop swap
定义
priority_queue<Type, Container, Functional>
Type
就是数据类型
Container
就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用list。STL里面默认是vector)
Functional
就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆
1 2 3 4 priority_queue<int , vector <int >, greater<int > > q; priority_queue<int , vector <int >, less<int > > q;
基本类型例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 int main () { priority_queue<int > a; priority_queue<int , vector <int >, greater<int > > c; priority_queue<string > b; for (int i = 0 ; i < 5 ; i++) { a.push(i); c.push(i); } while (!a.empty()) { cout << a.top() << " " ; a.pop(); } cout << endl ; while (!c.empty()) { cout << c.top() << " " ; c.pop(); } cout << endl ; b.push("abc" ); b.push("abcd" ); b.push("cbd" ); while (!b.empty()) { cout << b.top() << " " ; b.pop(); } cout << endl ; return 0 ; }
pair(先比较第一个元素,第一个相等再比较第二个元素)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int main () { priority_queue<pair<int , int > > a; pair<int , int > b(1 , 2 ); pair<int , int > c(1 , 3 ); pair<int , int > d(2 , 5 ); a.push(b); a.push(c); a.push(d); while (!a.empty()) { cout << a.top().first << " " << a.top().second << endl ; a.pop(); } return 0 ; }
对于自定义类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 struct node { int x; node(int a) { x = a; } bool operator < (const node &a) const { return x < a.x; } }; struct cmp { bool operator () (node a, node b) { return a.x < b.x; } }; int main () { node a (1 ) ; node b (2 ) ; node c (3 ) ; priority_queue<node> q; q.push(a); q.push(b); q.push(c); while (!q.empty()) { cout << q.top().x << " " ; q.pop(); } cout << endl ; priority_queue<node, vector <node>, cmp> f; f.push(a); f.push(b); f.push(c); while (!f.empty()) { cout << f.top().x << " " ; f.pop(); } cout << endl ; return 0 ; }