题解 P5013 【水の斗牛】
Update
Content
这题不好弄题意简述啊,说个大概吧,就是
规则自己去看题目去。
数据范围:
Gossip
这题目真的是卡了我好久,调了大概有
我当时在讨论区里问某个点的时候,某位红名大佬还给我回复道:
当时我就被吓着了,什么?迷你猪国杀?!然而,当时我看到通过数只有可怜的
Solution
正如出题者
看目前的两篇题解都没解释清楚具体的步骤(包括但不限于直接用注释讲解),所以我在这里将具体步骤跟大家讲讲。
首先要有一个大概的框架。这个大家应该都清楚,我下面就把大致的思路图摆出来。
没错,一场斗牛就是这四个步骤,首先我们要发牌,发到
那么接下来就是细节化的问题了。
0 变量定义 and 注意事项
为了避免之后的过程中造成的误解,我先把每一个变量下个定义:
一位玩家有以下的系数:
还有,不保证本题解不会很长,所以请做好心理准备。
1 发牌
发牌是以上这四个步骤中算比较简单的一步,但是需要注意的地方也很多。
发完牌之后最重要的一步就是处理出这张牌的点数和花色。我们发现,只有点数为
所以,处理点数时,我们只需要特判上面两种情况,剩下的就直接将数字字符转换为数字了,这里想必无需多说。
花色也只需要对应存储就行。
你以为发牌到这里就完了?
那么我上面用的这么多变量岂不都是摆设了吗?
那么之后预处理该怎么办?
所以,我们需要用到上面这些变量来存储信息。具体来说,
首先,我们假设手里有这样两张牌:黑桃10和红桃10,并假设红桃10是在比较之前
所以发牌的过程就模拟完了。
2 预处理出牌型
接下来就要预处理牌型了。
笔者提醒:在看这一部分时强烈建议去做 P6014,这样的话可以对这一部分有更加深的理解。另外,您也可以参考 P6014 处理好这一部分的细节问题。
根据大小顺序,我们先把炸弹处理,再把铁板和牛数一起处理。
那么这里
那么一般情况的牛数怎么算呢?
我们都知道,
我们这么想,如果我们直接枚举三个牌的点数,那么它的循环次数就是
如果我们只用枚举两个牌的点数的话,循环次数就是
还记得我们之前提到的
这里就应该让它起作用了!
因为前面我们已经预处理出了
那么判断该如何呢?
设我们枚举的两张牌的点数分别是
那么这里的牛数弄完之后,我们再和之前铁板的牛数相比较,如果铁板的牛数大于等于没有铁板的牛数,那么有铁板的情况肯定是最优的。这时我们将最终的牛数定为有铁板时的牛数。否则,因为我们首先要比较牛数,所以应该将没有铁板时的牛数定为最终的牛数。这里特别说明一下有铁板的牛数等于一般情况的牛数的情况。因为有铁板的话还可以翻倍,所以肯定它的牌型是比没铁板时的高的,所以我们应该选有铁板的牌型。
那么预处理牌型也弄完了。
3 两两比拼
这里有很多的坑点,可以说是本题的关键。
因为炸弹是最大的牌型,所以我们先比较炸弹。
因为在前面我们定义了如果没有炸弹则将
对于测试点
那么炸弹比较完我们再来比较牛数。如果牛数大就是牛数大的那方赢,所以直接根据大的一方的牛数翻倍就好了,如果牛数大的那方还有铁板,分数就再
如果都是无牛牌型呢?题目里已经讲得很明白,就和相同牛数且均无铁板时的处理办法一样,这里不再赘述了。
那么到这里,两两比拼也结束了。
4 统计分数
这个倒没什么必要讲的,直接利用
那么这个题目到这里就讲完了,自己去代码实现的时候注意一亿些细节就好。希望我这篇题解能够帮到更多人!(鞠躬
Code
目前我的
Orz排在我前面的三位巨佬
(
忽然发现用
引用 unordered_map内部实现是hash表,map内部实现是平衡树,所以可以大大提高算法效率。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <unordered_map>
#define F(i,a,b) for(int (i) = (a); (i) <= (b); ++(i))
using namespace std;
int useless, t, n;
struct player {
string name;
int card[7], num[17], col[7], sum, niu, tieban, maxx, bomb, idd;
long long score;
/*
card:记每个牌的点数
num:记每种点数出现在的牌的数量
col:记每张牌的花色
sum:记所有牌点数的和
niu:记牌的类型
niu=0-10 无牛、牛一至九、牛牛
tieban:记录铁板的点数,如果没有铁板则记为0。
maxx:记录所有牌中最大的点数
bomb:记录炸弹的点数,如果没有炸弹则记为0.
*/
}a[100007];
unordered_map<string, int> hashmap;
inline void cle(int id) {
memset(a[id].card, 0, sizeof(a[id].card));
memset(a[id].num, 0, sizeof(a[id].num));
memset(a[id].col, 0, sizeof(a[id].col));
a[id].sum = a[id].niu = a[id].tieban = a[id].maxx = a[id].bomb = a[id].idd = 0;
}
inline void premission(int t3) {
F(i, 1, 5) {
string cards;
cin >> cards;
if(cards[1] == '1' && cards[2] == '0') a[t3].card[i] = 10;
else if(cards[1] == 'A') a[t3].card[i] = 1;
else a[t3].card[i] = cards[1] - '0';
a[t3].sum += a[t3].card[i];
a[t3].num[a[t3].card[i]]++;
if(cards[0] == 'a') a[t3].col[i] = 4;
if(cards[0] == 'b') a[t3].col[i] = 3;
if(cards[0] == 'c') a[t3].col[i] = 2;
if(cards[0] == 'd') a[t3].col[i] = 1;
if(a[t3].card[i] > a[t3].maxx) {
a[t3].maxx = a[t3].card[i];
a[t3].idd = a[t3].col[i];
} else if(a[t3].card[i] == a[t3].maxx && a[t3].col[i] > a[t3].idd)
a[t3].idd = a[t3].col[i];
}
F(i, 1, 5) {
if(a[t3].num[a[t3].card[i]] == 4) {
a[t3].bomb = a[t3].card[i];
break;
}
if(a[t3].num[a[t3].card[i]] == 3) {
a[t3].tieban = a[t3].card[i];
if(!((a[t3].sum - a[t3].card[i] * 3) % 10)) a[t3].niu = 10;
else a[t3].niu = (a[t3].sum - a[t3].card[i] * 3) % 10;
}
F(j, 1, 5) {
if(i == j) continue;
if((a[t3].card[i] + a[t3].card[j]) % 10 == a[t3].sum % 10) {
int p = a[t3].niu;
if(!((a[t3].card[i] + a[t3].card[j]) % 10)) a[t3].niu = 10;
else a[t3].niu = max(a[t3].niu, (a[t3].card[i] + a[t3].card[j]) % 10);
if(a[t3].niu > p) a[t3].tieban = 0;
}
}
}
}
inline void pk(int id1, int id2) {
int difen = 10, sf = 0;
if(a[id1].bomb > a[id2].bomb) {
sf = 1;
difen *= 10;
} else if(a[id1].bomb < a[id2].bomb) {
sf = 2;
difen *= 10;
} else if(!a[id1].bomb && !a[id2].bomb) {
if(a[id1].niu > a[id2].niu) {
if(a[id1].niu == 10)
difen *= 3;
else if(a[id1].niu >= 7 && a[id1].niu <= 9)
difen *= 2;
else
difen *= 1;
if(a[id1].tieban) difen *= 2;
sf = 1;
} else if(a[id1].niu < a[id2].niu) {
if(a[id2].niu == 10)
difen *= 3;
else if(a[id2].niu >= 7 && a[id2].niu <= 9)
difen *= 2;
else
difen *= 1;
if(a[id2].tieban) difen *= 2;
sf = 2;
} else if(a[id1].niu == a[id2].niu && a[id1].niu) {
if(a[id1].tieban > a[id2].tieban) {
if(a[id1].niu == 10) difen *= 3;
else if(a[id1].niu >= 7 && a[id1].niu <= 9) difen *= 2;
else difen *= 1;
difen *= 2;
sf = 1;
} else if(a[id1].tieban < a[id2].tieban){
if(a[id2].niu == 10) difen *= 3;
else if(a[id2].niu >= 7 && a[id2].niu <= 9) difen *= 2;
else difen *= 1;
difen *= 2;
sf = 2;
} else if(a[id1].tieban == a[id2].tieban) {
if(a[id1].maxx > a[id2].maxx)
sf = 1;
else if(a[id1].maxx < a[id2].maxx)
sf = 2;
if(sf == 1) {
if(a[id1].niu == 10) difen *= 3;
else if(a[id1].niu >= 7 && a[id1].niu <= 9) difen *= 2;
else difen *= 1;
if(a[id1].tieban) difen *= 2;
} else if(sf == 2) {
if(a[id2].niu == 10) difen *= 3;
else if(a[id2].niu >= 7 && a[id2].niu <= 9) difen *= 2;
else difen *= 1;
if(a[id2].tieban) difen *= 2;
}
else {
if(a[id1].idd > a[id2].idd) {
sf = 1;
if(a[id1].niu == 10) difen *= 3;
else if(a[id1].niu >= 7 && a[id1].niu <= 9) difen *= 2;
else difen *= 1;
if(a[id1].tieban) difen *= 2;
}
else if(a[id1].idd < a[id2].idd) {
sf = 2;
if(a[id2].niu == 10) difen *= 3;
else if(a[id2].niu >= 7 && a[id2].niu <= 9) difen *= 2;
else difen *= 1;
if(a[id2].tieban) difen *= 2;
}
}
}
} else if(!a[id1].niu && !a[id2].niu) {
if(a[id1].maxx > a[id2].maxx)
sf = 1;
else if(a[id1].maxx < a[id2].maxx)
sf = 2;
else {
if(a[id1].idd > a[id2].idd)
sf = 1;
else if(a[id1].idd < a[id2].idd)
sf = 2;
}
}
}
if(sf == 1) a[id1].score += difen, a[id2].score -= difen;
else a[id1].score -= difen, a[id2].score += difen;
}
int main() {
scanf("%d%d%d", &useless, &t, &n);
F(i, 1, n) {
cin >> a[i].name;
hashmap[a[i].name] = i;
}
while(t--) {
string s1, s2, s3;
int t1, t2, t3;
cin >> s1; t1 = hashmap[s1];
premission(t1);
cin >> s2; t2 = hashmap[s2];
premission(t2);
cin >> s3; t3 = hashmap[s3];
premission(t3);
pk(t1, t2);
pk(t1, t3);
pk(t2, t3);
cle(t1), cle(t2), cle(t3);
}
F(i, 1, n) {
cout << a[i].name;
printf(" %lld\n", a[i].score);
}
return 0;
}
看在我写了这么多的份上,不点个赞再走嘛qwq。