[luoguP11323] Happy Card
题意
原题链接
有 种牌,第 种牌有 张,每次可以出 张(单牌)、 张(对子)或 张相同的牌(四炸),或是 张相同的牌及 张不同的牌(三带一),求把牌出完最少需要多少次。
sol
赛时看到这道题,就想到了 [luoguP2668]斗地主,由于没有顺子,因此可以直接考虑贪心。
反复审读题意,不难发现,后两种操作方式本质上都是 张牌带任意 张牌(下统称为三带一),因此处理出将所有相同的牌三个三个出需要出的次数 ,以及剩余 张及 张牌的种数 。然后贪心的取即可。
具体地,需要分类讨论两种情况:
- 所有的三张相同的牌可以将剩余的牌全部带出,此时,剩余的牌有以下几种情况:
- 剩余 组三张相同的牌,需要出一个对子及一张单牌,共 次;
- 剩余 组三张相同的牌,需要出一个三带一及一个对子,共 次;
- 剩余 组三张相同的牌,需要出两个三带一及一张单牌,共 次;
- 剩余 组三张相同的牌,需要出三个三带一,共 次;
- 剩余 组以上三张相同的牌,贪心地取,每次优先取 组三张相同的牌,当不够取时,按上述情况取即可。
- 所有的三张相同的牌不可以将剩余的牌全部带出,此时,优先带出剩余 张的牌,再优先带出剩余 张的牌。
证明比较简单,这里不说。
注意最终结果可能会爆 long long。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 300005;
int a[N];
int T, n;
int main(){
scanf("%d", &T);
while (T -- ){
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
int cnt1 = 0, cnt2 = 0;
long long cnt3 = 0;
for (int i = 1; i <= n; i ++ ){
cnt3 += a[i] / 3;
if (a[i] % 3 == 1) cnt1 ++ ;
if (a[i] % 3 == 2) cnt2 ++ ;
}
if (cnt3 >= cnt1 + cnt2 * 2) {
long long ans = cnt1 + cnt2 * 2 + (cnt3 - cnt1 - 2 * cnt2) / 4 * 3 + (cnt3 - cnt1 - 2 * cnt2) % 4;
if ((cnt3 - cnt1 - cnt2 * 2) % 4 == 1) ans ++ ;
printf("%lld\n", ans);
}
else {
long long ans;
if (cnt3 < cnt1) ans = cnt2 + cnt1;
else ans = cnt3 + (cnt2 * 2 - (cnt3 - cnt1) + 1) / 2;
printf("%lld\n", ans);
}
}
}
分类:
题解 / 2024赛时
标签:
基础算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构