P8836 [传智杯 #3 决赛] 打牌 题解
题目分析
本题是一道比较简单的模拟题,根据题意直接模拟即可。
读入数据可以用桶存储牌的数量自动排序。
有几点需要注意一下:
-
判断“两个人都无法打出牌时”需要注意是连续两人无法打出牌。
-
在每次进行下一个回合前都需要注意初始化。
具体见代码。
#include<bits/stdc++.h>
using namespace std;
const int N = 105;
int n,m,box[3][N];
bool pd(int idx) // 判断是否结束了(即有人获胜了
{
int flag = 1;
for (int i = 0;i <= m;i++) if (box[idx][i]) flag = 0;
return flag;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i = 0;i < 3;i++)
for (int j = 1;j <= n;j++)
{
int x;
scanf("%d",&x);
box[i][x]++;//桶排序
}
int tplastman = 0;//即题目中“打出最后一张牌的人”,初始设为0
while (1) // 最外层的循环循环游戏回合数 直到有人获胜跳出循环
{
//初始化 idx为当前出牌者的编号 cnt为当前需要出的牌的张数
//cur 为 上一次出的牌的点数 loser为有多少人不能打出牌
int idx = tplastman,cnt = 1,cur = -1,loser = 0;
// 第二层的while循环多轮的游戏,直到“一轮中,其余两个人都无法打出牌”跳出循环
while (true)
{
//flag:当前编号的人能否打出牌
//flag2:能否增加牌的张数
bool flag = 0,flag2 = 0;
//循环遍历直到可以打出牌或确认无法打出牌
while(!flag)
{
//遍历桶
for (int i = 0;i <= m;i++)
{
//若可以打出
if (box[idx][i] >= cnt && i > cur)
{
box[idx][i] -= cnt;
cur = i;
flag = 1;
tplastman = idx;
loser = 0;//清空
break;
}
//如果有牌的张数大于当前张数,则可以增加张数
if (box[idx][i] > cnt) flag2 = 1;
}
//若可以继续增加牌的张数,继续循环
if (flag == 0 && flag2) cnt++,cur = -1;
else if (flag == 0 && flag2 == 0) break;//跳出循环
}
//打不出牌
if (flag == 0) loser++;
if (loser >= 2) break;
if (pd(idx))
{
//结束后直接输出
cout << idx+1 << endl;
return 0;
}
idx = (idx + 1) % 3;
}
}
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下