NOIP模拟 poke - 贪心
题目大意:
给一副牌(\(n \le 1000000, a_i \le 1000000\)),问最多能打出多少对对子(x, x)或者顺子(x, x + 1, x + 2)。
题目分析:
感觉跟斗地主很像,然后直接贪心了对子,少考虑了很多情况,30分。
贪心:处理l, r, 对于当前点数l,先贪心将对子取完,对剩下的两种情况分别处理:
- 剩余0: 直接处理l+1, r
- 剩余1: 如果l+1有偶数个,不管这一个,直接处理l+1, r
如果l+1有奇数个,并且l,l+1,l+2能够组成顺子,那么组成顺子,处理l+1, r
一个递归就可以解决。
做了斗地主才知道原来贪心题难起来也不是盖的。
code
#include<bits/stdc++.h>
using namespace std;
namespace IO{
inline int read(){
int i = 0, f = 1; char ch = getchar();
for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
if(ch == '-') f = -1, ch = getchar();
for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
return i * f;
}
inline void wr(int x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) wr(x / 10);
putchar(x % 10 + '0');
}
}using namespace IO;
const int N = 1E6+5;
int n, x, b[N], maxx = -1;
inline int solve(int l, int r){
int ret = 0;
while(b[l] >= 2) b[l] -= 2, ret++;
if(l == r) return ret;
if(b[l]){ //还剩一张
if(l + 2 <= r && b[l + 1] && b[l + 2] && (b[l + 1] & 1)) b[l]--, b[l + 1]--, b[l + 2]--, ret++; //下一码数个数是奇数
}
return ret + solve(l + 1, r);
}
int main(){
n = read();
for(int i = 1; i <= n; i++) {x = read(), b[x]++, maxx = max(maxx, x);}
wr(solve(1, maxx));
return 0;
}