其他分享
首页 > 其他分享> > LuoguP2348 三国杀I(洗牌&发牌) 题解

LuoguP2348 三国杀I(洗牌&发牌) 题解

作者:互联网

Content

浓缩版:将牌库里的 \(k\) 张牌洗 \(m\) 次,然后将其分发给 \(n\) 个玩家,问第 \(p\) 号玩家的 \(4\) 张牌都有哪些。

完整版:Link

Solution

直接对照题意模拟一遍即可。反正写过近 \(200\) 行的模拟代码,这样的模拟还算是简单的了。

我们在输入完 \(n,k,m,p\) 以后可以直接判断出牌是否够。因为每个人都要有 \(4\) 张牌,所以牌库里面必须要有足够 \(n\) 个人有四张牌的储存数量。也就是说,\(k\geqslant 4n\)。所以,如果 \(k<4n\) 的话牌肯定不够,于是直接退出程序。

牌够的话就继续下面的洗牌和发牌过程,由题意我们可以明显的看出,这道题目中牌的花色、点数和类型纯粹就是用来作为输入输出的载体,没有什么实质性的用处(实质性的用处可以参考P2482。那么直接按照题目里的要求洗就是了。

首先要注意的是牌库里储存的牌的数量的问题,因为它可能是奇数,所以我们应该按照题目里的要求直接忽略掉它。那么如何存储洗过之后的牌呢?我们在这里考虑另起一个结构体来存储,然后将所有的信息全部用来覆盖掉原来的信息。

最后就是发牌了,因为题目中只需要知道第 \(p\) 个人的所有牌,所以只需要当轮到 \(p\) 的时候直接输出当前的牌就可以了。题目中给了我们这样的公式:

第 \(i\) 张牌分给第 \([(i-1)\mod n+1]\) 号玩家。

所以直接套公式,然后看它等于 \(p\) 的时候直接输出牌的所有信息即可。

Code

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;

struct cd {
	string cn, t;
}c1[100007], c2[100007];
int n, k, m, p;

int main() {
	scanf("%d%d%d%d", &n, &k, &m, &p);
	for(int i = 1; i <= k; ++i)
		cin >> c1[i].cn >> c1[i].t;
	if(k < n * 4) {
		printf("Error:cards not enough");
		return 0;
	}
	if(k % 2)	k--;
	while(m--) {
		for(int i = 1; i <= k - 1; i += 2) {
			c2[i] = c1[k / 2 + (i + 1) / 2];
			c2[i + 1] = c1[(i + 1) / 2];
		}
		for(int i = 1; i <= k; ++i)
			c1[i] = c2[i];
	}
	int cnum = 0;
	for(int i = 1; i <= k; ++i)
		if((i - 1) % n + 1 == p) {
			cnum++;
			if(cnum > 4)	break;
			cout << c1[i].cn << ' ' << c1[i].t << '\n';
		}
	return 0;
}

标签:题目,int,题解,d%,张牌,LuoguP2348,include,发牌
来源: https://www.cnblogs.com/Eason-AC/p/15725101.html