1A : 飞飞的赌神修炼手册
飞飞很喜欢打牌,他决定苦练牌技,终成赌神!
飞飞有 A × B 张扑克牌。每张扑克牌有一个大小(整数,记为 a,范围区间是 0 到 A - 1)和一个花色(整数,记为 b,范围区间是 0 到 B - 1。
扑克牌是互异的,也就是独一无二的,也就是说没有两张牌大小和花色都相同。
“一手牌”的意思是你手里有 5 张不同的牌,这 5 张牌没有谁在前谁在后的顺序之分,它们可以形成一个牌型。 我们定义了 9 种牌型,如下是 9 种牌型的规则,我们用“低序号优先”来匹配牌型,即这“一手牌”从上到下满足的第一个牌型规则就是它的“牌型编号”(一个整数,属于 1 到 9):
- 同花顺: 同时满足规则 5 和规则 4.
- 炸弹 : 5张牌其中有4张牌的大小相等.
- 三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
- 同花 : 5张牌都是相同花色的.
- 顺子 : 5张牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
- 三条: 5张牌其中有3张牌的大小相等.
- 两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
- 一对: 5张牌其中有2张牌的大小相等.
- 要不起: 这手牌不满足上述的牌型中任意一个.
现在, 飞飞从 A × B 张扑克牌中拿走了 2 张牌!分别是 (a1, b1) 和 (a2, b2). (其中a表示大小,b表示花色)
现在要从剩下的扑克牌中再随机拿出 3 张!组成一手牌!!
其实飞飞现在要预言他的未来的可能性,即他将拿到的“一手牌”的可能性,我们用一个 “牌型编号(一个整数,属于 1 到 9)” 来表示这手牌的牌型,那么他的未来有 9 种可能,但每种可能的方案数不一样。
现在飞飞想要计算一下 9 种牌型中,每种牌型的方案数。
Input
第 1 行包含了整数 A 和 B (1 ≤ A ≤ 25, 1 ≤ B ≤ 4).
第 2 行包含了整数 a1, b1, a2, b2 (0 ≤ a1, a2 ≤ A - 1, 0 ≤ b1, b2 ≤ B - 1, (a1, b1) ≠ (a2, b2)).
Output
输出一行,这行有 9 个整数,每个整数代表了 9 种牌型的方案数(按牌型编号从小到大的顺序)
限制:设计程序进行枚举,不能使用数学公式推导出每种牌型的方案数式子!
限制:设计程序进行枚举,不能使用数学公式推导出每种牌型的方案数式子!
限制:设计程序进行枚举,不能使用数学公式推导出每种牌型的方案数式子!
测试样例
样例 1
输入:文章来源:https://www.toymoban.com/news/detail-418515.html
5 2
1 0 3 1
输出:
0 0 0 0 8 0 12 36 0
样例 2
输入:
25 4
0 0 24 3
输出:
0 2 18 0 0 644 1656 36432 113344
解答
#include <bits/stdc++.h>
using namespace std;
int main()
{
int A, B;
cin >> A >> B;
int a1, b1, a2, b2;
cin >> a1 >> b1 >> a2 >> b2;
int ff[9], f[9];
for (int i = 0; i < 9; i++)
{
f[i] = 0;
ff[i] = 0;
}
vector<pair<int, int>> s(5);
pair<int, int> m, v;
m.first = a1;
v.first = a2;
m.second = b1;
v.second = b2;
s[0] = m;
s[1] = v;
// s.push_back(m);
// s.push_back(v);
for (int i = 0; i < A; i++)
{
for (int j = 0; j < B; j++)
{
if (((i != s[0].first) || (j != s[0].second)) && (i != s[1].first || j != s[1].second))
{
pair<int, int> s1;
s1.first = i;
s1.second = j;
s[2] = s1;
for (int ii = 0; ii < A; ii++)
{
for (int jj = 0; jj < B; jj++)
{
if ((ii != s[0].first || jj != s[0].second) && (ii != s[1].first || jj != s[1].second) && (ii != s[2].first || jj != s[2].second))
{
pair<int, int> ss;
ss.first = ii;
ss.second = jj;
// s.push_back(ss);
s[3] = ss;
for (int iii = 0; iii < A; iii++)
{
for (int jjj = 0; jjj < B; jjj++)
{
if ((iii != s[0].first || jjj != s[0].second) && (iii != s[1].first || jjj != s[1].second) && (iii != s[2].first || jjj != s[2].second) && (iii != s[3].first || jjj != s[3].second))
{
pair<int, int> sss;
sss.first = iii;
sss.second = jjj;
// s.push_back(sss);
s[4] = sss;
vector<pair<int, int>> aa(5);
for (int k = 0; k < 5; k++)
{
aa[k] = s[k];
}
sort(aa.begin(), aa.end()); // 排序
int h = 0; // 前后相减差1的个数
int hh = 0; // 花色相同的个数
int y = 0; // 三张牌相同的个数
int yy = 0; // 前后数字相同的个数
for (int i = 0; i < 4; i++)
{
if (aa[i].first == aa[i + 1].first - 1)
{
h++;
}
if (aa[i].second == aa[i + 1].second)
{
hh++;
}
if (i <= 2)
{
if (aa[i].first == aa[i + 2].first)
{
y++;
}
}
if (aa[i].first == aa[i + 1].first)
{
yy++;
}
}
if (h == 4 && hh == 4) //同花顺
{
f[0]++;
ff[0] = 1;
}
else if (y == 2 && yy == 3) // 炸弹
{
f[1]++;
ff[1] = 1;
}
else if (y == 1 && yy == 3) // 三带二
{
f[2]++;
ff[2] = 1;
}
else if (hh == 4 && h != 4) // 相同花色
{
f[3]++;
ff[3] = 1;
}
else if (h == 4 && hh != 4) // 顺子
{
f[4]++;
ff[4] = 1;
}
else if (y == 1) //三张牌相同
{
f[5]++;
ff[5] = 1;
}
else if (yy == 2) // 两对
{
f[6]++;
ff[6] = 1;
}
else if (yy == 1) // 一对
{
ff[7] = 1;
f[7]++;
}
else
{
f[8]++;
}
// s.pop_back();
}
}
}
// s.pop_back();
}
}
}
// s.pop_back();
}
}
}
for (int i = 0; i < 9; i++)
{
cout << f[i] / 6 << " ";
}
cout << endl;
return 0;
}
2B : TT与可怜的猫
题目描述
自从 TT 成为了助教,他就热衷于给同学们解答疑问,于是他就没有时间进行陪他的猫猫玩了,真是一只可怜的小猫。
TT 在同一时间会与很多同学同时用 QQ(TT 特供版) 进行答疑,有时 TT 开启一个新的窗口,开始一个新的答疑对话;有时 TT 关闭一个窗口,结束一段答疑; 有时,为了及时回答着急的同学,TT 会把一个对话窗口设置为置顶状态(置顶状态是一种虚拟的状态,窗口的实际位置并不会发生改变)。
你可以将 TT 的聊天窗口想象成一个队列。如果现在没有窗口处于置顶状态,那么在队列中位列第一窗口视为在顶层,否则处于置顶状态的窗口视为在顶层。请注意,不可能同时存在两个窗口处于置顶状态(也就是说,处于置顶状态的窗口,要么不存在,要么只有一个)。如果当前置顶的窗口被关闭了,则剩余队列中第一窗口视为在顶层。
TT 为了安抚自己的猫,于是给猫猫看自己的聊天记录解闷,根据猫猫看屏幕中窗口的时间,TT 给每个窗口分配了一个喜爱度,TT 认为喜爱度越高,猫猫越开心。由于猫猫具有不确定的生物特性,所以所有的喜爱度都是不同的。
作为 TT 特供版 QQ 的研发人员,你要负责完成的工作是为软件记录 TT 的操作,形成一个日志系统。日志有固定的记录格式:OpId #X: MSG.
,其中 X 是操作的编号,而 MSG
是日志的提示信息,需要使用特定的字符串进行替换。
TT 可能会用到的操作如下:
-
Add u: TT 打开一个喜爱度为 u 的新窗口,若 u 不与当前窗口队列中的某个窗口重复,则该新窗口将新建成功,并成为窗口队列中的最后一个窗口。 如果创建成功,则
MSG
记录success
。 否则,MSG
记录same likeness
。 -
Close u: TT 关掉了一个喜爱度为 u 的窗口,如果该窗口存在,则将其关闭,
MSG
记录close u with c
,u 表示喜爱度,c 表示该窗口上次打开至今交流的话的数量。若该窗口不存在,则MSG
记录invalid likeness
。 -
Chat w: TT 和顶层窗口交流了 w 句话,如果当前队列中没有窗口,则
MSG
记录empty
,否则记录success
。 -
Rotate x: 将队列中第 x 个窗口放在队首,若 x 大于当前队列中窗口数或小于 1 ,则
MSG
记录out of range
,否则记录success
。举个例子,目前队列中有喜爱度为 5,3,2,8 的四个窗口,Rotate 3 之后,会将喜爱度为 2 的第 3 个窗口放在首位,结果为 2,5,3,8。 -
Prior: TT 将目前喜爱度最大的窗口放在队首,如果当前队列中没有窗口,则
MSG
记录empty
,否则记录success
。 -
Choose u: TT 将喜爱度为 u 的窗口放在队首,如果喜爱度为 u 的窗口存在,则
MSG
记录success
,否则记录invalid likeness
。 -
Top u: TT 将喜爱度为 u 的窗口设定为置顶状态,如果喜爱度为 u 的窗口存在,则
MSG
记录success
,否则记录invalid likeness
。注意,处于置顶状态的窗口最多不超过一个,也就是说,如果在此次设定前已经有处于置顶状态的窗口,则原有置顶状态的窗口的置顶状态将会消失。(置顶只是一种虚拟的状态,原窗口在队列中的位置不会发生变化) -
Untop: TT 取消当前处于置顶状态窗口的置顶状态。如果当前没有窗口处于置顶状态,则
MSG
记录no such person
,否则记录success
。
最后,由于 TT 要给自己的猫猫树立一个讲文明有礼貌的榜样,所以在上述操作完成后,还要进行若干次操作,这些操作是:与当前队列中所有说过话的窗口说拜拜。MSG
记录 Bye u: c
, u 表示喜爱度,c 表示该窗口上次打开至今交流的话的数量。即:TT 先和位于顶层的窗口说拜拜,然后将其关闭,如果 TT 没有和当前顶层窗口说过话,则直接将其关闭,如此操作下去,直到队列为空。
输入描述
第一行包含一个整数 T(T≤5),表示数据组数。
对于每组数据,第一行一个 n,表示执行的操作数,其中 0<n≤5000。接下来 n 行,每行输入一个操作,保证所有输入数据中的整数不大于 109。
输出描述
对于每个指定的操作,按照日志的格式,每个操作行。对于最后的非指定操作,同样按照日志的格式,每个操作一行。
测试样例
样例 1
输入:
1
30
Add 4
Add 3
Chat 4
Add 3
Rotate 2
Chat 5
Prior
Top 3
Choose 4
Rotate 1
Add 2
Close 4
Chat 7
Choose 2
Chat 7
Add 3
Top 2
Add 4
Choose 3
Chat 7
Prior
Top 3
Rotate 1
Rotate 3
Chat 7
Top 4
Add 2
Close 2
Prior
Add 4
输出:
OpId #1: success.
OpId #2: success.
OpId #3: success.
OpId #4: same likeness.
OpId #5: success.
OpId #6: success.
OpId #7: success.
OpId #8: success.
OpId #9: success.
OpId #10: success.
OpId #11: success.
OpId #12: close 4 with 4.
OpId #13: success.
OpId #14: success.
OpId #15: success.
OpId #16: same likeness.
OpId #17: success.
OpId #18: success.
OpId #19: success.
OpId #20: success.
OpId #21: success.
OpId #22: success.
OpId #23: success.
OpId #24: success.
OpId #25: success.
OpId #26: success.
OpId #27: same likeness.
OpId #28: close 2 with 7.
OpId #29: success.
OpId #30: same likeness.
OpId #31: Bye 3: 26.
解答
#include <bits/stdc++.h>
using namespace std;
// #define inf 1e6
long long T;
long long n;
long long tot;
struct Window
{
long long x, y; // y为说话量,x为喜欢程度,z为是否打开
/* data */
} w[1000000];
long long top; // 置顶的窗口的序号
string a;
long long b;
// pair<long long, long long> C[1000000]; // first为喜爱度,second为是否打开
// 初始化
void init()
{
for (long long i = 0; i < 1000000; i++)
{
// C[i].first = -1;
// C[i].second = 0;
w[i].x = -1;
w[i].y = 0;
// w[i].z = 0;
// w[i].k = 0;
}
// w[1]. = 1;
tot = 1;
}
long long j;
void play(long long i);
void bye();
int main()
{
// freopen("1.txt", "r", stdin);
// freopen("2.txt", "w", stdout);
cin >> T;
for (long long i = 1; i <= T; i++)
{
cin >> n;
init();
top = -1;
for (j = 1; j <= n; j++)
{
cin >> a;
play(j);
}
bye();
}
// system("pause");
return 0;
}
void bye()
{
if (top != -1)
{
if (w[top].y != 0)
{
// j++;
cout << "OpId #" << j << ": ";
cout << "Bye " << w[top].x << ": " << w[top].y << "." << endl;
j++;
}
// }
for (long long i = 1; i < tot; i++)
{
if (w[i].x == w[top].x || w[i].y == 0)
{
continue;
}
else
{
// j++;
cout << "OpId #" << j << ": ";
cout << "Bye " << w[i].x << ": " << w[i].y << "." << endl;
j++;
}
}
}
else
{
for (long long i = 1; i < tot; i++)
{
if (w[i].y != 0)
{
cout << "OpId #" << j << ": ";
cout << "Bye " << w[i].x << ": " << w[i].y << "." << endl;
j++;
}
}
}
}
void play(long long i)
{
// switch (a)
// {
if (a == "Add")
{
cin >> b;
long long g = 1;
for (; g < tot; g++)
{
if (w[g].x == b)
{
break;
}
}
// long long d = 1;
// for (; d < tot; d++)
// {
// if (C[d].first == b)
// {
// break;
// }
// }
if (g >= tot)
{
w[tot].x = b;
// C[tot] = 1;
tot++;
cout << "OpId #" << i << ": success." << endl;
}
// else if (C[d].second == 0)
// {
// cout << "OpId #" << i << ": success." << endl;
// }
else
{
cout << "OpId #" << i << ": same likeness." << endl;
}
// C[tot - 1] = 1;
// C[tot - 1].first = b;
// C[tot - 1].second = 1;
// break;
}
else if (a == "Close")
{
cin >> b;
long long g = 1;
for (; g < tot; g++)
{
if (w[g].x == b)
{
break;
}
}
if (g >= tot)
{
cout << "OpId #" << i << ": invalid likeness." << endl;
}
else
{
if (top > g && top != -1)
{
top--;
}
else if (top == g)
{
top = -1;
}
cout << "OpId #" << i << ": close " << b << " with " << w[g].y << "." << endl;
for (int h = g; h < tot - 1; h++)
{
w[h].x = w[h + 1].x, w[h].y = w[h + 1].y;
}
w[tot - 1].x = -1, w[tot - 1].y = 0;
tot--;
// long long d = 1;
// for (; d < tot; d++)
// {
// if (C[d].first == b)
// {
// break;
// }
// }
// if (C[d].second != 0)
// {
// C[d].second = 0;
// w[g].z = 0;
// w[g].y = 0;
// }
// else
// {
// cout << "OpId #" << i << ": invalid likeness." << endl;
// }
}
// break;
}
else if (a == "Chat")
// case "Chat":
{
cin >> b;
if (tot == 1)
{
cout << "OpId #" << i << ": empty." << endl;
}
else
{
if (top == -1)
{
w[1].y = b + w[1].y;
// C[1].second = 1;
cout << "OpId #" << i << ": success." << endl;
}
else
{
// if (C[top].second == 0)
// {
// w[1].y = b;
// C[1] = 1;
cout << "OpId #" << i << ": success." << endl;
// }
// else
// {
w[top].y = b + w[top].y;
// C[top] = 1;
// }
}
}
}
else if (a == "Rotate")
// case "Rotate":
{
cin >> b;
if (b >= tot || b < 1)
{
cout << "OpId #" << i << ": out of range." << endl;
}
else
{
if (top < b && top != -1)
{
top++;
}
else if (top == b)
{
top = 1;
}
long long x1, y1, z1;
x1 = w[b].x, y1 = w[b].y;
for (long long g = b; g > 1; g--)
{
w[g].x = w[g - 1].x;
w[g].y = w[g - 1].y;
// w[g].z = w[g - 1].z;
}
w[1].x = x1, w[1].y = y1;
cout << "OpId #" << i << ": success." << endl;
}
// break;
}
else if (a == "Prior")
// case "Prior":
{
if (tot == 1)
{
cout << "OpId #" << i << ": empty." << endl;
}
else
{
cout << "OpId #" << i << ": success." << endl;
long long f = 1;
long long u = w[1].x;
for (long long g = 1; g < tot; g++)
{
if (w[g].x > u)
{
u = w[g].x;
f = g;
}
}
if (top < f && top != -1)
{
top++;
}
else if (top == f)
{
top = 1;
}
long long x1, y1, z1;
x1 = w[f].x, y1 = w[f].y;
for (long long g = f; g > 1; g--)
{
w[g].x = w[g - 1].x;
w[g].y = w[g - 1].y;
// w[g].z = w[g - 1].z;
}
w[1].x = x1, w[1].y = y1;
}
// break;
}
else if (a == "Choose")
// case "Choose":
{
cin >> b;
long long g = 1, f = -1;
for (; g < tot; g++)
{
if (w[g].x == b)
{
f = g;
break;
}
}
if (f < tot && f != -1)
{
long long x1, y1, z1;
if (top < f && top != -1)
{
top++;
}
else if (top == f)
{
top = 1;
}
x1 = w[f].x, y1 = w[f].y;
for (long long h = f; h > 1; h--)
{
w[h].x = w[h - 1].x;
w[h].y = w[h - 1].y;
}
w[1].x = x1, w[1].y = y1;
cout << "OpId #" << i << ": success." << endl;
}
else
{
cout << "OpId #" << i << ": invalid likeness." << endl;
}
// break;
}
else if (a == "Top")
// case "Top":
{
cin >> b;
long long g = 1, f = -1;
for (; g < tot; g++)
{
if (w[g].x == b)
{
f = g;
break;
}
}
if (f < tot && f != -1)
{
top = f;
cout << "OpId #" << i << ": success." << endl;
}
else
{
cout << "OpId #" << i << ": invalid likeness." << endl;
}
// break;
}
else if (a == "Untop")
// case "Untop":
{
// long long g = 1;
// for (; g < tot; g++)
// {
// // if (w[g].k == 2)
// // {
// // break;
// // }
// }
if (top != -1)
{
top = -1;
cout << "OpId #" << i << ": success." << endl;
}
else
{
cout << "OpId #" << i << ": no such person." << endl;
}
// break;
}
// }
}
3C : 记事本
注:本题有较多的部分分,请参看数据规模部分。
题目描述
记事本是 Windows 平台下一款经典的文本编辑器,其存储文件的扩展名为 .txt
,文件属性没有任何格式标签或者风格,所以相当适合在 DOS 环境中编辑。
在本题中,可能会用到的按键如下图所示:
光标移动
光标表示当前要进行输入等操作的位置,在本题中,我们假设所有字符都是等宽的。
光标的位置可以用行列坐标来描述,光标所在的行和列均从 1 开始,例如:
以下操作可以进行光标的移动,使用 MOVE <comd>
输入相关的操作,其中 <comd>
表示指令,可以使用以下字符串代替:
-
Home
:把光标移动到当前行的开头。 -
End
:把光标移动到当前行的末尾。 -
Up
:光标移动到上一行的相同列。- 若当前为第一行,则不进行任何操作。
- 若上一行的列数小于当前光标的列数,则将光标移动到上一行的末尾。
-
Down
:光标移动到下一行的相同列。- 若当前为最后一行,则不进行任何操作。
- 若下一行的列数小于当前光标的列数,则将光标移动到下一行的末尾。
-
Left
:光标左移一位。- 若当前光标位于记事本开始,则不进行任何操作。
- 若当前光标处于某一行的开头,则将光标移动到上一行的末尾。
-
Right
:光标右移一位。- 若当前光标位于记事本末尾,则不进行任何操作。
- 若当前光标处于某一行的末尾,则将光标移动到下一行的开头。
输入
以下操作可以在光标后进行输入,使用 INSERT <comd>
输入相关的操作,其中 <comd>
表示指令,可以使用以下字符串代替:
-
Char <char>
:输入一个字符,其中<char>
是输入的字符。-
<char>
可能是一下字符中的任意一个:
注:下列字符中不包含空格与换行符。
`1234567890-=~!@#$%^&*()_+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:"zxcvbnm,./ZXCVBNM<>?
- 例如:
INSERT Char a
表示在当前光标后插入a
字符。
-
-
Enter
:输入换行符,并进行换行。 -
Space
:输入空格。 -
Paste
:在当前光标后,插入粘贴板中的内容,若粘贴板中无内容,则忽略当前操作。
删除
以下操作可以删除记事本中的内容,使用 REMOVE <comd>
输入相关的操作,其中 <comd>
表示指令,可以使用以下字符串代替:
-
Del
:删除当前光标位置之后的一个字符。- 若该字符为换行符,则当前行与下一行合并为一行。
- 若当前光标在文件末尾,则忽略当前操作。
-
Backspace
:删除当前光标位置之前的一个字符。- 若该字符为换行符,则当前行与上一行合并为一行。
- 若当前光标在文件开头,则忽略当前操作。
粘滞功能(分数占比 24 分)
输入 SHIFT
指令,可以启动或关闭粘滞功能。
-
开始时粘滞功能默认为关闭状态,之后每次点击:
- 若当前为启动状态,则关闭;
- 若当前为关闭状态,则启动。
-
粘滞功能启动时,记录当前的光标位置为 记录点。
-
粘滞功能关闭时,若此时的光标位置与 记录点 的位置不同,则进入选中状态。
-
粘滞功能启动后,直到功能关闭前,不会对记事本进行除光标移动外的任何操作。
当进入选中状态后,通过记录点与当前光标,可以唯一的确定一段内容,现令记录点与光标之间的所有字符(包括换行符)为 选中字段。
例如,记录点位于第 1 行第 2 列,光标位于第 2 行第 4 列时,选中字段如下图所示:
当前 处于选中状态 时,对于不同的情况,需要按照序号依次执行以下操作:
-
若进行光标移动:
- 退出选中状态;
- 尝试进行光标的移动(无论光标最终是否移动,都会退出选中状态)。
-
若进行输入:
- 将选中内容替换为输入内容;
- 退出选中状态。
-
若进行删除:
- 删除当前选中内容;
- 退出选中状态。
-
若再次启动粘滞功能:退出选中状态,但保留上一次选中字段的 记录点 作为当前记录点。
-
若进行查找,字数统计,复制,打印操作,则在操作后仍然保持选中状态。
查找
输入 FIND <word>
指令,进行字符串查找,其中 <word>
为输入的要查找的字符串,该字符串中不包含空格与换行符。
执行该指令时,要根据当前是否处于选中状态做不同的处理:
- 若当前处于选中状态:查找输入字符串在选中字段中的出现次数并输出。
- 否则:查找输入字符串在当前记事本中的出现次数并输出。
例如:当前没有选中的内容,且记事本中的内容为 ababa
,若执行 FIND aba
,则应当输出 2,分别在第 1 列与第 3 列出现过。
字数统计
输入 COUNT
指令,进行字数统计。
执行该指令时,要根据当前是否处于选中状态做不同的处理:
- 若当前处于选中状态:输出当前选中字段中的可见字符(不包括空格与换行符)的数量。
- 否则:输出当前文档中可见字符(不包括空格与换行符)的数量。
复制
输入 COPY
指令,进行复制操作。
执行该指令时,要根据当前是否处于选中状态做不同的处理:
- 若当前处于选中状态:复制选中字段到粘贴板;
- 否则,
- 若当前行不为空:复制当前行的内容(不包括换行符)到粘贴板;
- 否则:忽略当前操作。
打印
输入 PRINT
指令,输出当前的记事本中的全部内容,并在之后输出一个换行符。
输入格式
输入包含 n+1 行。
第一行包含一个整数 n,表示接下来指令的数量。
接下来 n 行,每行一条指令,格式形如题目描述中的叙述。
输出格式
对于需要输出的指令,进行相应的输出。
若为 FIND
与 COUNT
操作,输出一行表示相应的数字。
若为 PRINT
操作,则输出若干行,表示记事本的当前内容,并在之后输出一个换行。
请注意:所有的输出不要有多余的空格。
测试样例
样例输入
20
INSERT Char #
INSERT Enter
INSERT Char C
INSERT Enter
INSERT Space
INSERT Char _
INSERT Char _
PRINT
INSERT Char >
INSERT Enter
INSERT Char h
INSERT Char h
INSERT Char h
INSERT Enter
PRINT
COUNT
FIND __
REMOVE Del
REMOVE Backspace
PRINT
样例输出
#
C
__
#
C
__>
hhh
8
1
#
C
__>
hhh
数据规模
对于 100% 的测试数据,1≤n≤5000。
不同测试点所包含的功能不同,其具体情况如下表所示。
解答
#include <bits/stdc++.h>
using namespace std;
const string NULLSTR = "null";
const string ENTER = "\n";
const string SPACE = " ";
vector<string> line; //lines of the file
vector<string> pasteBin; //lines of pasteBin
vector<string> selBin; //lines of selection
struct pos
{
int row = 1, col = 1;
bool operator<(const pos &pp) const
{
if (row == pp.row)
return col < pp.col;
return row < pp.row;
}
bool operator==(const pos &pp) const
{
return (row == pp.row) && (col == pp.col);
}
pos(int r, int c) : row(r), col(c) {}
pos() { row = col = 1; }
};
pos Cursor; //position of the Cursor 0=row,1=column,element=1,2,...
bool shifted = false; //shift enabled or not.
bool inSelection = false; //selection mode enabled or not.
pos remPoint; //remPoint for selection. (Just a copy of the Cursor there.)
pos selection[2]; //selection area.
int getSpeciLineIndex(const pos &p) { return p.row - 1; }
int getSpeciCharIndex(const pos &p) { return p.col - 2; }
int getSpeciLineFullLength(const pos &p) { return line[getSpeciLineIndex(p)].length(); } //get the string length of current line.
int getSpeciLineVisLength(const pos &p)
{
if (*(line[getSpeciLineIndex(p)].rbegin()) == '\n')
return line[getSpeciLineIndex(p)].length() - 1;
return getSpeciLineFullLength(p);
}
string getSpeciCursorLeftSub(const pos &p) { return line[getSpeciLineIndex(p)].substr(0, p.col - 1); } //get the substring on the left of the Cursor of the line.
string getSpeciCursorRightSub(const pos &p) { return line[getSpeciLineIndex(p)].substr(p.col - 1); } //get the substring on the right of the Cursor of the line.
string getSpeciLineVisStr(const pos &p) { return line[getSpeciLineIndex(p)].substr(0, getSpeciLineVisLength(p)); }
void theCopy(vector<string> &);
vector<string> getSelectionArea()
{ //return the range of selection. if not in selection, then return the whole file.
vector<string> range;
if (inSelection)
{
// pasteBinBackUp=pasteBin;
theCopy(selBin);
range = selBin;
// pasteBin=pasteBinBackUp;
}
else
range = line;
return range;
}
void Move(int type)
{
inSelection = false;
bool moveLR = false;
if(type == 1){
Cursor.col = 1;
}else if(type == 2){
Cursor.col = getSpeciLineVisLength(Cursor) + 1;
}else if(type==3){
if (Cursor.row == 1)
return;
moveLR = false;
if (getSpeciLineVisLength(pos(Cursor.row - 1, Cursor.col)) < Cursor.col - 1)
moveLR = true; //moded getCurLineLength().
--Cursor.row;
if (moveLR)
Move(2);
}else if(type ==4){
if (Cursor.row == line.size())
return;
moveLR = false;
if (getSpeciLineVisLength(pos(Cursor.row + 1, Cursor.col)) < Cursor.col - 1)
moveLR = true; //moded getCurLineLength().
++Cursor.row;
if (moveLR)
Move(2);
}else if(type==5){
if (Cursor.row == 1 && Cursor.col == 1)
return;
if (Cursor.col == 1)
{
Move(3);
Move(2);
return;
}
--Cursor.col;
}else if(type ==6){
if (Cursor.row == line.size() && Cursor.col == getSpeciLineVisLength(Cursor) + 1)
return;
if (Cursor.col == getSpeciLineVisLength(Cursor) + 1)
{ //moded getCurLineLength().
Move(4);
Move(1);
return;
}
++Cursor.col;
}else if(type ==7){
Cursor.col = getSpeciLineVisLength(Cursor) + 2; //moded getCurLineLength().
}
}
void insert(int, string arg);
void createNextLineWithStr(string str)
{
auto ins = line.begin();
for (int i = 1; i <= getSpeciLineIndex(Cursor); i++)
++ins;
line.insert(++ins, str);
Move(4);
Move(2);
}
void theCopy(vector<string> &bin)
{
if (inSelection)
{
bin.clear();
if (selection[0].row == selection[1].row)
{
int leftIndex = getSpeciCharIndex(selection[0]) + 1;
int rightIndex = getSpeciCharIndex(selection[1]);
if (leftIndex >= 0 && rightIndex >= 0)
bin.push_back(line[getSpeciLineIndex(selection[1])].substr(leftIndex, rightIndex - leftIndex + 1));
}
else
{
int upCharIndex = getSpeciCharIndex(selection[0]) + 1;
int upLineIndex = getSpeciLineIndex(selection[0]);
int dnCharIndex = getSpeciCharIndex(selection[1]);
int dnLineIndex = getSpeciLineIndex(selection[1]);
if (upCharIndex >= 0)
bin.push_back(line[upLineIndex].substr(upCharIndex));
else
bin.push_back(line[upLineIndex]);
for (int i = upLineIndex + 1; i < dnLineIndex; i++)
{
string tmp = line[i];
bin.push_back(tmp);
}
if (dnCharIndex >= 0)
bin.push_back(line[dnLineIndex].substr(0, dnCharIndex + 1));
}
return;
}
else if (getSpeciLineVisLength(Cursor) != 0)
{
bin.clear();
bin.push_back(getSpeciLineVisStr(Cursor));
return;
}
}
void theRemove(int);
void insert(int type, string arg)
{
vector<string>::iterator ins;
string left, right;
if (inSelection)
{
if (type == 4 && pasteBin.empty())
return;
if (selection[1] == selection[0])
{
Cursor = selection[1];
inSelection = false;
insert(type, arg);
return;
}
theRemove(1); //type can be any value.
insert(type, arg);
inSelection = false;
return;
}
switch (type)
{
case 1:
line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + arg + getSpeciCursorRightSub(Cursor);
Cursor.col += arg.length();
break;
case 2:
right = getSpeciCursorRightSub(Cursor);
line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + ENTER;
ins = line.begin();
for (int i = 1; i <= getSpeciLineIndex(Cursor); i++)
++ins;
line.insert(++ins, right);
Move(4);
Move(1);
break;
case 3:
line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + SPACE + getSpeciCursorRightSub(Cursor);
++Cursor.col;
break;
case 4:
if (pasteBin.empty())
return;
right = getSpeciCursorRightSub(Cursor);
if (pasteBin.size() == 1 && *(pasteBin[0].rbegin()) != '\n')
{
line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + pasteBin[0] + right;
for (int i = 0; i < pasteBin[0].size(); i++)
Move(6);
}
else
{
int curLine = -1;
line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + pasteBin[++curLine];
for (int i = 1; i < pasteBin.size() - 1; i++)
createNextLineWithStr(pasteBin[++curLine]);
if (*(pasteBin[pasteBin.size() - 1].rbegin()) != '\n')
{
if (curLine + 1 <= pasteBin.size() - 1)
createNextLineWithStr(pasteBin[pasteBin.size() - 1] + right);
Move(1);
for (int i = 0; i < pasteBin[pasteBin.size() - 1].size(); i++)
Move(6);
}
else
{
if (curLine + 1 <= pasteBin.size() - 1)
createNextLineWithStr(pasteBin[pasteBin.size() - 1]);
createNextLineWithStr(right);
Move(1);
}
}
break;
}
}
void theRemove(int type)
{
vector<string>::iterator ins;
string left, right;
if (inSelection)
{
theCopy(selBin);
left = getSpeciCursorLeftSub(selection[0]);
right = getSpeciCursorRightSub(selection[1]);
Cursor = selection[0];
line[getSpeciLineIndex(selection[0])] = left + right;
int firstDelLineIndex;
firstDelLineIndex = getSpeciLineIndex(selection[0]) + 1;
for (int i = firstDelLineIndex; i <= selection[1].row - 1;)
{
ins = line.begin();
for (int j = 1; j <= i; j++)
++ins;
line.erase(ins);
--selection[1].row;
}
inSelection = false;
if (Cursor.row > line.size())
{
Move(3);
Move(2);
}
return;
}
switch (type)
{
case 1:
if (getSpeciLineIndex(Cursor) + 1 == line.size() && getSpeciCharIndex(Cursor) == getSpeciLineVisLength(Cursor) - 1)
return; //moded getCurLineLength().
if (getSpeciCharIndex(Cursor) == getSpeciLineVisLength(Cursor) - 1)
{ //moded getCurLineLength().
line[getSpeciLineIndex(Cursor)] = getSpeciLineVisStr(Cursor) + line[getSpeciLineIndex(Cursor) + 1];
ins = line.begin();
for (int i = 1; i <= getSpeciLineIndex(Cursor); i++)
++ins;
line.erase(++ins);
return;
}
left = getSpeciCursorLeftSub(Cursor);
right = getSpeciCursorRightSub(Cursor).substr(1);
line[getSpeciLineIndex(Cursor)] = left + right;
break;
case 2:
if (getSpeciCharIndex(Cursor) == -1 && getSpeciLineIndex(Cursor) == 0)
return;
if (getSpeciCharIndex(Cursor) == -1)
{
pos tmpCurs = Cursor; //backup the Cursor. so we can move the Cursor before line is merged.
Move(3);
Move(2);
line[getSpeciLineIndex(tmpCurs) - 1] = getSpeciLineVisStr(pos(tmpCurs.row - 1, tmpCurs.col)) + line[getSpeciLineIndex(tmpCurs)];
ins = line.begin();
for (int i = 1; i <= getSpeciLineIndex(tmpCurs); i++)
++ins;
line.erase(ins);
return;
}
left = getSpeciCursorLeftSub(Cursor).substr(0, getSpeciCharIndex(Cursor));
right = getSpeciCursorRightSub(Cursor);
line[getSpeciLineIndex(Cursor)] = left + right;
--Cursor.col; //Cursor goes back 1 char.
break;
}
}
int theFind(string word)
{
vector<string> range = getSelectionArea();
int ans = 0;
for (string curLine : range)
{
int fIndex = 0;
while (fIndex < curLine.length() && (fIndex = curLine.find(word)) != string::npos)
{
++ans;
curLine = curLine.substr(fIndex + 1);
fIndex = 0;
}
}
return ans;
}
void shift()
{
shifted = !shifted;
if (shifted)
{
if (inSelection)
{
inSelection = false;
return;
}
remPoint = Cursor;
}
else
{
if (remPoint == Cursor)
return;
if (remPoint < Cursor)
{
selection[0] = remPoint;
selection[1] = Cursor;
}
else
{
selection[1] = remPoint;
selection[0] = Cursor;
}
inSelection = true;
}
}
int theCount()
{
vector<string> range = getSelectionArea();
int ans = 0;
for (string str : range)
for (char c : str)
if (c != ' ' && c != '\n')
ans++;
return ans;
}
void thePrint()
{
for (string str : line)
if (!str.empty())
cout << str;
cout << endl;
}
int main()
{
ios::sync_with_stdio(false);
int opCnt;
cin >> opCnt;
line.emplace_back("");
string op, arg1;
bool insertChar = false; //for debug.
for (int opI = 1; opI <= opCnt; opI++)
{
insertChar = false;
cin >> op;
switch(op[0]){
case 'M': {
cin >> arg1;
switch(arg1[0]){
case 'H':{
Move(1);
break;
}
case 'E':{
Move(2);
break;
}
case 'U':{
Move(3);
break;
}
case 'D':{
Move(4);
break;
}
case 'L':{
Move(5);
break;
}
case 'R':{
Move(6);
break;
}
}
break;
}
case 'I':
{
cin >> arg1;
switch(arg1[0]){
case 'C':{
string arg2;
cin >> arg2;
insert(1, arg2);
insertChar = true; // for debug.
break;
}
case 'E':{
insert(2, NULLSTR);
break;
}
case 'S':{
insert(3, NULLSTR);
break;
}
case 'P':{
insert(4, NULLSTR);
break;
}
}
break;
}
case 'R': {
cin >> arg1;
if (arg1 == "Del")
{
theRemove(1);
}
else if (arg1 == "Backspace")
{
theRemove(2);
}
break;
}
case 'S':{
shift();
break;
}
case 'F':{
cin >> arg1;
int ans = theFind(arg1);
cout << ans << endl;
break;
}
case 'C':{
if(op[2]=='P'){
theCopy(pasteBin);
}else if(op[2]=='U'){
cout << theCount() << endl;
}
break;
}
case 'P':{
thePrint();
break;
}
}
}
return 0;
}
4D : 猪国杀(模板)
请使用指定的代码模板完成该题~
- 由于原题在题面和数据上的一些小问题,本题经过了一些小修小改,数据,和题面,与 SDOI2010 略有不同。参考网络资料将让你在完成作业的路径上绕远路(不保证可行)并且收获甚少。相信自己,独立完成会收获很多,你也可以在思考无所获后向同学请教。
- 代码模板精心制作,请大家理解后进行补全代码实验
- 本题代码模板不严格遵守面向对象的规则,而是面向教育用途设计
- 比起费力优化代码的常数复杂度,更乐于精心设计将代码逻辑区分开
- 本实验考点:
- 问题理解及其逻辑化能力
- 大型(显然并不大 第三方代码框架理解和分析能力
- 工程改动的创口分析和实践能力
- 程序调试能力
- 期末将近,预祝同学们期末考得好成绩,不负努力,加油。
背景
《猪国杀》是一种多猪牌类回合制游戏,一共有 3 种角色:主猪,忠猪,反猪。每局游戏主猪有且只有 1 只,忠猪和反猪可以有多只,每只猪扮演 1 种角色。
目的
主猪 / MP:自己存活的情况下消灭所有的反猪。
忠猪 / ZP:不惜一切保护主猪,胜利条件与主猪相同。
反猪 / FP:杀死主猪。
游戏过程
游戏开始时,每个玩家手里都会有 4 张牌,且体力上限和初始体力都是 4 。
开始游戏时,从主猪开始,按照逆时针方向(数据中就是按照编号从 1,2,3…n 的顺序)依次行动。
每个玩家自己的回合可以分为 2 个阶段:
- 摸牌阶段:从牌堆顶部摸 2 张牌,依次放到手牌的最右边;
- 出牌阶段:你可以使用任意张牌,每次使用牌的时候都使用最靠左的能够使用的牌。当然,要满足如下规则:
- 如果没有猪哥连弩,每个出牌阶段只能使用 1 次「杀」来攻击;
- 任何牌被使用后被弃置(武器是装备上);被弃置的牌以后都不能再用,即与游戏无关。
各种牌介绍
每张手牌用 1 个字母表示,字母代表牌的种类。
基本牌
『桃 / P』在自己的回合内,如果自己的体力值不等于体力上限,那么使用 1 个桃可以为自己补充 1 点体力,否则不能使用桃;桃只能对自己使用;在自己的回合外,如果自己的血变为 0 或者更低,那么也可以使用。
『杀 / K』在自己的回合内,对攻击范围内除自己以外的 1 名角色使用。如果没有被『闪』抵消,则造成 1 点伤害。无论有无武器,杀的攻击范围都是 1。
『闪 / D』当你受到杀的攻击时,可以弃置 1 张闪来抵消杀的效果。
锦囊牌
『决斗 / F』出牌阶段,对除自己以外任意 1 名角色使用,由目标角色先开始,自己和目标角色轮流弃置 1 张杀,首先没有杀可弃的一方受到 1 点伤害,另一方视为此伤害的来源。
『南猪入侵 / N』出牌阶段,对除你以外所有角色使用,按逆时针顺序从使用者下家开始依次结算,除非弃置 1 张杀,否则受到 1 点伤害。
『万箭齐发 / W』和南猪入侵类似,不过要弃置的不是杀而是闪。
『无懈可击 / J』在目标锦囊生效前抵消其效果。每次有 1 张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会;效果:用于决斗时,决斗无效并弃置;用于南猪入侵或万箭齐发时,当结算到某个角色时才能使用,当前角色不需弃置牌并且不会受到伤害(仅对 1 个角色产生效果);用于无懈可击时,成为目标的无懈可击被无效。
装备牌
『猪哥连弩 / Z』武器,攻击范围 1 ,出牌阶段你可以使用任意张杀; 同一时刻最多只能装 1 把武器;如果先前已经有了 1 把武器,那么之后再装武器的话,会弃置以前的武器来装现在的武器。
特殊事件及概念解释
伤害来源:杀、南猪入侵、万箭齐发的伤害来源均是使用该牌的猪,决斗的伤害来源如上;
距离:两只猪的距离定义为沿着逆时针方向间隔的猪数 +1 。即初始时 1 和 2 的距离为 1 ,但是 2 和 1 的距离就是 n−1 。注意一个角色的死亡会导致一些猪距离的改变;
玩家死亡:如果该玩家的体力降到 0 或者更低,并且自己手中没有足够的桃使得自己的体力值回到 1 ,那么就死亡了,死亡后所有的牌(装备区,手牌区)被弃置
奖励与惩罚:反猪死亡时,最后一个伤害来源处(即使是反猪)立即摸 3 张牌。忠猪死亡时,如果最后一个伤害来源是主猪,那么主猪所有装备牌、手牌被弃置。
注意:一旦达成胜利条件,游戏立刻结束,因此即使会摸 3 张牌或者还有牌可以用也不用执行了。
现在,我们已经知道每只猪的角色、手牌,还有牌堆初始情况,并且假设每个角色会按照如下的行为准则进行游戏,你需要做的就是告诉最后的结果。
几种行为:
献殷勤:使用无懈可击挡下南猪入侵、万箭齐发、决斗;使用无懈可击抵消表敌意的锦囊效果;
表敌意:对某个角色使用杀、决斗;使用无懈可击抵消献殷勤的锦囊效果;
跳忠:即通过行动表示自己是忠猪。跳忠行动就是对主猪或对某只已经跳忠的猪献殷勤,或者对某只已经跳反的猪表敌意;
跳反:即通过行动表示自己是反猪。跳反行动就是对主猪或对某只已经跳忠的猪表敌意,或者对某只已经跳反的猪献殷勤。
注意:忠猪不会跳反,反猪也不会跳忠;不管是忠猪还是反猪,能够跳必然跳。
行动准则
共性
- 每个角色如果手里有桃且生命值未满,那么必然吃掉;
- 有南猪入侵、万箭齐发、必然使用;有装备必然装上;
- 受到杀时,有闪必然弃置;
- 响应南猪入侵或者万箭齐发时候,有杀 / 闪必然弃置;
- 不会对未表明身份的猪献殷勤(包括自己)。
特性
主猪:
- 主猪会认为「没有跳身份,且用南猪入侵 / 万箭齐发对自己造成伤害的猪」是类反猪(没伤害到不算,注意类反猪并没有表明身份),如果之后跳了,那么主猪会重新认识这只猪;
- 对于每种表敌意的方式,对逆时针方向能够执行到的第一只已跳反猪表;如果没有,对逆时针方向能够执行到的第一只类反猪表,再没有,那么就不表敌意;
- 决斗时会不遗余力弃置杀;
- 如果能对已经跳忠的猪或自己献殷勤,那么一定献;如果能够对已经跳反的猪表敌意,那么一定表。
忠猪:
- 对于每种表敌意的方式,对「逆时针方向能够执行到的第一只已经跳反的猪」表,如果没有,那么就不表敌意;
决斗时,如果对方是主猪,那么不会弃置杀,否则,会不遗余力弃置杀; - 如果有机会对主猪或者已经跳忠的猪献殷勤,那么一定献。
反猪:
- 对于每种表敌意的方式,如果有机会则对主猪表,否则,对「逆时针方向能够执行到的第一只已经跳忠的猪」表,如果没有,那么就不表敌意;
- 决斗时会不遗余力弃置杀;
- 如果有机会对已经跳反的猪献殷勤,那么一定献。
输入格式
输入文件第一行包含两个正整数 n(2⩽n⩽10) 和 m(m⩽2000),分别代表玩家数和牌堆中牌的数量。数据保证牌的数量够用。
接下来 n 行,每行 5 个字符串,依次表示对第 i 只猪的角色和初始 4 张手牌描述。编号为 1 的肯定是主猪。
再接下来一行,一共 m 个字符串,按照从牌堆顶部到牌堆底部的顺序描述每张牌。
注意:所有的相邻的两个字符串都严格用 1 个空格隔开,行尾没有多余空格。
输出格式
输出数据第一行包含一个字符串代表游戏结果。如果是主猪胜利,那么输出 MP ,否则输出 FP 。数据保证游戏总会结束。
接下来 n 行,第 i 行是对第 i 只猪的手牌描述(注意只需要输出手牌),按照手牌从左往右的顺序输出,相邻两张牌用 1 个空格隔开,行末尾没有多余空格。如果这只猪已阵亡,那么只要输出 DEAD 即可。
注意:如果要输出手牌而没有手牌的话,那么只需输出 1 个空行。
样例
Input:
3 10
MP D D F F
ZP N N N D
FP J J J J
F F D D J J F F K D
Output:
FP
DEAD
DEAD
J J J J J J D
解释:
-
第一回合:
- 主猪没有目标可以表敌意;
- 接下来忠猪使用了 3 张南猪入侵,主猪掉了 3 点体力,并认为该角色为类反猪,3 号角色尽管手里有无懈可击,但是因为自己未表明身份,所以同样不能对自己用,乖乖掉 3 点体力;
-
下一回合:
- 反猪无牌可出;
- 接下来主猪对着类反猪爆发,使用 4 张决斗,忠猪死亡,结果主猪弃掉所有牌;
子任务
一共 20 组测试数据,每个点 5 分。
10% 的数据没有锦囊牌,另外 20% 的数据没有无懈可击。
测试样例
样例 1
输入:
3 25
MP K K K K
ZP Z Z Z Z
FP J J J J
K K Z Z J J K K W Z W W K Z J J K K J J K K W W W
输出:文章来源地址https://www.toymoban.com/news/detail-418515.html
FP
DEAD
DEAD
J J J J J J J J J J W
解答
// 杀
bool Pig::useK(){
Pig *nxt = getNextPig(); // 获取下一只猪
// 判断使用杀的猪是什么身份
if(this->type == 'M'){ // 主猪
if(nxt->jumpType == 'f' or nxt->jumpType=='F'){ // 判断下一只猪的跳的身份
nxt->cost(this, 'D');
return true;
}
}else if(this->type=='Z'){ // 忠猪
if(nxt ->jumpType=='F'){ // 阵营为F则使用
nxt->cost(this, 'D');
this->jumpType = 'Z';
return true;
}
}else if(this->type=='F'){ // 反猪
if(nxt->jumpType=='Z'){ // 判断是否是忠猪阵营
nxt->cost(this, 'D');
this->jumpType = 'F';
return true;
}
}
return false;
}
// 南蛮入侵
bool Pig::useN() {
for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
// TODO: 补全代码
if(!nxt->findJ(this)){ // 没有人使用无懈可击
bool dd = nxt->cost(this, 'K');
if(!dd and nxt->type=='M' and this->jumpType==0){ // 没有跳身份
this->jumpType = 'f';
}
}
}
return true;
}
// 万箭齐发
bool Pig::useW() {
for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
// TODO: 补全代码
if(!nxt->findJ(this)){ // 没人使用无懈可击
bool dd = nxt->cost(this, 'D');
if(!dd and nxt->type=='M' and this->jumpType==0){ // 没有跳身份
this->jumpType = 'f';
}
}
}
return true;
}
// 决斗
bool Pig::useF(){
char rr = this->type;
// int gg = this->index; //
if(rr == 'Z'){ // 判断使用者身份
int ff;
bool pp = false;
Pig *it;
for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
if(nxt->jumpType=='F'){
// ff = nxt->index;
it = nxt;
pp = true;
break;
}
}
if(!pp){
return false;
}
this->jumpType = 'Z';
if(!it->findJ(this)){ // 判断是否有人使用无懈可击
while(true){
if(!it->cost(this, 'K')) // 进行决斗,两个人相互出杀
break;
if(!this->cost(it,'K'))
break;
}
}
return true;
}else if(rr == 'F'){
this->jumpType = 'F';
if(!ps[0].findJ(this)){
while(true){
if(!ps[0].cost(this,'K'))
break;
if(!this->cost(&ps[0],'K'))
break;
}
}
return true;
}else if(rr == 'M'){
int lf=100000, ff=100000;
// 寻找第一个F和f
for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
if(nxt->jumpType=='F'){
if(nxt->index < ff){
ff = nxt->index;
}
}
if(nxt->jumpType =='f'){
if (lf > nxt->index){
lf = nxt->index;
}
}
}
// 有F存在时
if(ff < n){
if(!ps[ff].findJ(this)){
while(true){
if(!ps[ff].cost(this,'K'))
break;
// return true;
if(!this->cost(&ps[ff],'K'))
break;
// return true;
}
}
return true;
}else if(lf < n){ // F不存在,但是f存在时
if(!ps[lf].findJ(this)){
if(ps[lf].type == 'Z'){
ps[lf].hurt(this);
}else{
while(true){
if(!ps[lf].cost(this,'K'))
// return true;
break;
if(!this->cost(&ps[lf],'K'))
break;
// return true;
}
}
}
return true;
}
}
return false;
}
// 删除一张牌
bool Pig::del(char c){
// Pig *nxt = getNextPig();
// int gg = this->index;
for (list<char>::iterator i = this->cards.begin(); i != this->cards.end();i++){ // 寻找牌
if(c != *i)
continue;
else{ // 有就删除,没有就返回false
this->cards.erase(i);
return true;
}
}
return false;
}
到了这里,关于Vj程序设计复杂模拟题训练的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!