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;
}
posted @ 2017-10-19 17:20  CzYoL  阅读(240)  评论(0编辑  收藏  举报