Duizi and Shunzi(贪心)

题目链接: Duizi and Shunzi

大致题意

给你n张牌, 每张牌都是1~n之中的数字, 你可以选择两张数值一样的牌凑成一个对子, 你也可以选择三张数值连续的牌凑成顺子. 每张牌只可以使用一次.

问: 最多能凑出多少对子和顺子.

解题思路

首先我们需要产生尽可能多的对子和顺子, 那么一个对子需要两张牌, 一个顺子需要三张牌.

因此优先级: 对子 > 顺子

考虑到题目中所有的ai都 <= n, 因此我们可以用桶排序的思路来记录每一个数字出现的情况.

由于优先级的因素, 因此对于一张牌而言, 如果自身能成对子, 则就要成尽可能多的对子. 我们不难想到, 若该牌数量为偶数, 则无剩余, 若为奇数, 则有一张剩余.

那么对于该牌数量为奇数的情况, 他有可能和其余牌组成顺子, 那么我们如何判断该不该组成顺子呢?

这里先给出一种错误的想法, 如果你想着我们贪心, 先把所有能组成对子的组成对子, 然后再考虑是否组成顺子, 是不正确的.

例如样例: 1 2 3 3 4 5 很显然组成两个顺子是最优的, 但是如果按照上述做法, 只能组成一个对子.

在这里我们需要从小到大枚举所有的牌(意味着枚举到i时, i+1与i+2数量均为原先的数量, 也没有自身组成对子), 如果当前x为奇数张 且 x+1, x+2牌均存在的情况下, 我们需要考虑是否需要组成顺子.

这里的考虑方式还是通过优先级. 我们为什么先考虑对子再考虑顺子? 因为对子的代价为2, 顺子的代价为3. 那么如果我们可以降低顺子的代价, 不就可以使得顺子的优先级提升吗?

这里再提供一种错误的想法, 如果你认为, 我当前的x不是奇数张吗? 那么我直接把 x, x + 1, x + 2组成顺子, 这样代价不也是2吗? 这种情况下的顺子和对子的优先级相同, 应该结果是一样的吧? 然后你去敲代码, 发现你又错了!

这里给出一组例子: 1 2 2 3 3 很显然答案是2, 但是你这样做, 答案就是1了.

这里的原因是, 由于我们从小到大枚举, 组成的对子是无后效性的, 而你组成顺子时, 你会对没有遍历到的x+1和x+2的位置产生影响. 因此我们不能单纯的认为这样的顺子代价也是2.

当且仅当x和x+1均为奇数张, 且x+2存在时, 我们组成顺子才是优于对子的. 此时由于x和x+1都是奇数张, 可以认为代价只由x+2产生, 因此代价为1. 相当于我们仅消耗了一张牌, 就使得了结果+1.

AC代码

//头文件
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E6 + 10;
int a[N];
int main()
{
    int n;
    while (~scanf("%d", &n)) {
        rep(i, n + 2) a[i] = 0;
        
        rep(i, n) {
            int x; scanf("%d", &x);
            a[x]++;
        }
        
        int res = 0;
        rep(i, n) {
            res += a[i] / 2;
            if (a[i] % 2 and a[i + 1] % 2 and a[i + 2]) {
                rep(j, 3) a[i + j - 1]--;
                res++;
            }
        }
        printf("%d\n", res);
    }
    return 0;
}

END

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值