·A - 化学 (编译器选 GNU G++)
原题目如下
化学很神奇,以下是烷烃基。
假设如上图,这个烷烃基有6个原子和5个化学键,6个原子分别标号1~6,然后用一对数字 a,b 表示原子a和原子b间有一个化学键。这样通过5行a,b可以描述一个烷烃基
你的任务是甄别烷烃基的类别。
原子没有编号方法,比如
1 2
2 3
3 4
4 5
5 6
和
1 3
2 3
2 4
4 5
5 6
是同一种,本质上就是一条链,编号其实是没有关系的,可以在纸上画画就懂了Input
输入第一行为数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b),数据保证,输入的烷烃基是以上5种之一
Output
每组数据,输出一行,代表烷烃基的英文名
Example
Input
2
1 2
2 3
3 4
4 5
5 6
1 4
2 3
3 4
4 5
5 6
Output
n-hexane
3-methylpentane
问题分析:
从化学角度找规律,是比较容易的。有i个碳碳键的原子数目可以很好的统计出来,比如,3-methylpentane中,3个原子有1个碳碳键,2个原子有2个碳碳键,中间1个原子有1个碳碳键。考虑到这点性质和2-methylpentane一样,但是和剩下的三个都不一样,而且剩下的三个各不一样,所以接下来区分2-methylpentane和2-methylpentane。
显然可以记录含3个碳碳键的碳原子及与其相邻的碳原子。对于2-methylpentane来说,与它相邻的碳原子,有2个含1个碳碳键,有1个含两个碳碳键。
#include <iostream> using namespace std; int main() { int n; cin >> n; for (int i = 0; i < n; ++i) { int num_key[5];//有i个键的原子的数目 for (int p = 0; p < 5; ++p) num_key[p] = 0; int atom_key[7];//第i的原子的键的数目,i=1,2,...,6 for (int p = 0; p < 7; ++p) atom_key[p] = 0; int matrix[7][7]; for (int p = 0; p < 7; ++p) for (int q = 0; q < 7; ++q) matrix[p][q] = 0; int a, b; for (int j = 0; j < 5; ++j) { cin >> a >> b; matrix[a][b] = 1; matrix[b][a] = 1; atom_key[a]++; atom_key[b]++; } for (int r = 1; r <= 6; ++r) { if (atom_key[r] == 1) num_key[1]++; else if (atom_key[r] == 2) num_key[2]++; else if (atom_key[r] == 3) num_key[3]++; else if (atom_key[r] == 4) num_key[4]++; } if (num_key[1] == 2 && num_key[2] == 4) cout << "n-hexane" << endl; else if (num_key[1] == 3 && num_key[2] == 2 && num_key[3] == 1) { int atom_key3; for (int w = 1; w <= 6; ++w) if (atom_key[w] == 3) atom_key3 = w; int temp1 = 0; int temp2 = 0; for (int u = 1; u <= 6; ++u) { if (matrix[atom_key3][u] == 1) { if (atom_key[u] == 1) temp1++; else if (atom_key[u] == 2) temp2++; } } if (temp1 == 2) cout << "2-methylpentane" << endl; else cout << "3-methylpentane" << endl; } else if (num_key[1] == 4 && num_key[2] == 0 && num_key[3] == 2) cout << "2,3-dimethylbutane" << endl; else if (num_key[1] == 4 && num_key[2] == 1 && num_key[4] == 1) cout << "2,2-dimethylbutane" << endl; } return 0; }
·B - 爆零(×)大力出奇迹(√)
原题目如下
我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回AC,要么是返回各种其他的错误,不论是怎样的错法,它总会给你记上一笔,表明你曾经在这儿被坑过,而当你历经千辛终将它AC之后,它便会和你算笔总账,表明这题共错误提交了几次。
在岁月的长河中,你通过的题数虽然越来越多,但通过每题时你所共花去的时间(从最开始算起,直至通过题目时的这段时间)都会被记录下来,作为你曾经奋斗的痕迹。特别的,对于你通过的题目,你曾经的关于这题的每次错误提交都会被算上一定的单位时间罚时,这样一来,你在做出的题数上,可能领先别人很多,但是在做出同样题数的人中,你可能会因为罚时过高而处于排名上的劣势。
例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上了一对括号,里面有个正数b,则表示该学生AC了这道题,耗去了时间a,同时曾经错误提交了b次。例子可见下方的样例输入与输出部分。
Input输入数据包含多行,第一行是共有的题数n(1≤n≤12)以及单位罚时m(10≤m≤20),之后的每行数据描述一个学生的信息,首先是学生的用户名(不多于10个字符的字串)其次是所有n道题的得分现状,其描述采用问题描述中的数量标记的格式,见上面的表格。
Output根据这些学生的得分现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。
Sample Input
8 20 GuGuDong 96 -3 40(3) 0 0 1 -8 0 hrz 107 67 -3 0 0 82 0 0 TT 120(3) 30 10(1) -3 0 47 21(2) -2 OMRailgun 0 -99 -8 0 -666 -10086 0 -9999996 yjq -2 37(2) 13 -1 0 113(2) 79(1) -1 Zjm 0 0 57(5) 0 0 99(3) -7 0
Sample Output
TT 5 348 yjq 4 342 GuGuDong 3 197 hrz 3 256 Zjm 2 316 OMRailgun 0 0
问题分析:
着重做以下三件事:
1,将参赛者的信息用结构体储存起来,包括姓名,ac数目,得分
2,读入数据,判断读入的格式,计算或者直接将相关信息填入结构体中
3,写排序规则,排序后输出
具体来说,比较难的是读入数据。使用助教的方法,用scanf从键盘读入字符串,然后用sscanf读字符串到指定变量,是最方便的,容易区分得分和罚时。我用的方法很繁琐,是分析、判断string,从string中读有效的数据。这一点需要注意。
#include <iostream> #include <string> #include <algorithm> #include <iomanip> using namespace std; struct node { string name; int ac = 0; int score = 0; }; node stu[10005]; bool cmp(const node& x, const node& y) { if (x.ac != y.ac) return x.ac > y.ac; else if (x.score != y.score) return x.score < y.score; else return x.name < y.name; } int main() { int n, m; cin >> n >> m; int t = 0; while (cin >> stu[t].name) { stu[t].ac = 0; stu[t].score = 0; for (int i = 0; i < n; i++) { string info; cin >> info; if (info[0] == '-') continue; if (info[0] == '0') continue; stu[t].ac++; int len = info.length(); int p, s = 0; for (p = 0; p < len; p++) { if (info[p] == '(') break; s = s * 10 + info[p] - '0'; } stu[t].score += s; s = 0; if (p < len) { for (int k = p + 1; k < len - 1; k++) { s = s * 10 + info[k] - '0'; } } stu[t].score += s * m; } t++; } sort(stu, stu + t, cmp); for (int i = 0; i < t; ++i) { cout << setiosflags(ios::left) << setw(10) << stu[i].name; printf_s(" %2d %4d ", stu[i].ac, stu[i].score); } return 0; }
·C-瑞神打牌
原题目如下
显然,牌局由四个人构成,围成一圈。我们称四个方向为北 东 南 西。对应的英文是North,East,South,West。游戏一共由一副扑克,也就是52张构成。开始,我们指定一位发牌员(东南西北中的一个,用英文首字母标识)开始发牌,发牌顺序为顺时针,发牌员第一个不发自己,而是发他的下一个人(顺时针的下一个人)。这样,每个人都会拿到13张牌。
现在我们定义牌的顺序,首先,花色是(梅花)<(方片)<(黑桃)<(红桃),(输入时,我们用C,D,S,H分别表示梅花,方片,黑桃,红桃,即其单词首字母)。对于牌面的值,我们规定2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。
现在你作为上帝,你要从小到大排序每个人手中的牌,并按照给定格式输出。(具体格式见输出描述和样例输出)。
Input
每组数据的第一行包含一个大写字符,表示发牌员是谁。如果该字符为‘#’则表示输入结束。
接下来有两行,每行有52个字符,表示了26张牌,两行加起来一共52张牌。每张牌都由两个字符组成,第一个字符表示花色,第二个字符表示数值。
Output
每组数据应该由24行的组成,输出按照顺时针方向,始终先输出South Player的结果,每位玩家先输出一行即玩家名称(东南西北),接下来五行,第一行和第五行输出固定格式(见样例),第二行和第四行按顺序和格式输出数值(见样例),第三行按顺序和格式输出花色(见样例)。
Sample Input
N CTCAH8CJD4C6D9SQC7S5HAD2HJH9CKD3H6D6D7H3HQH4C5DKHKS9 SJDTS3S7S4C4CQHTSAH2D8DJSTSKS2H5D5DQDAH7C9S8C8S6C2C3 #
Sample Output
South player: +---+---+---+---+---+---+---+---+---+---+---+---+---+ |6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T| | C | C | D | D | S | S | S | S | H | H | H | H | H | |6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T| +---+---+---+---+---+---+---+---+---+---+---+---+---+ West player: +---+---+---+---+---+---+---+---+---+---+---+---+---+ |2 2|5 5|9 9|K K|5 5|7 7|9 9|4 4|T T|J J|A A|8 8|A A| | C | C | C | C | D | D | D | S | S | S | S | H | H | |2 2|5 5|9 9|K K|5 5|7 7|9 9|4 4|T T|J J|A A|8 8|A A| +---+---+---+---+---+---+---+---+---+---+---+---+---+ North player: +---+---+---+---+---+---+---+---+---+---+---+---+---+ |3 3|4 4|J J|2 2|3 3|T T|Q Q|K K|8 8|Q Q|K K|2 2|3 3| | C | C | C | D | D | D | D | D | S | S | S | H | H | |3 3|4 4|J J|2 2|3 3|T T|Q Q|K K|8 8|Q Q|K K|2 2|3 3| +---+---+---+---+---+---+---+---+---+---+---+---+---+ East player: +---+---+---+---+---+---+---+---+---+---+---+---+---+ |7 7|8 8|T T|Q Q|4 4|8 8|A A|2 2|3 3|6 6|J J|Q Q|K K| | C | C | C | C | D | D | D | S | S | H | H | H | H | |7 7|8 8|T T|Q Q|4 4|8 8|A A|2 2|3 3|6 6|J J|Q Q|K K| +---+---+---+---+---+---+---+---+---+---+---+---+---+
问题分析
牌的顺序已经定下来了,只需要分发给四个玩家即可。使用简单的循环,用一个结构体数组代表一个玩家,每个结构体代表一张扑克,储存花色和大小,然后读入发牌顺序,从指定的玩家开始,顺时针依次发牌给玩家。
值得注意的是,单独写两个函数,一个是吧花色转化为整数,例如,按照规则,A最大,所以定为14,然后T,J,Q,K一次是10,11,12,13,其余数字转化为相应的整数就可以了。这样有利于排序。另一个函数正好相反,把储存的数转化为代表花色的字符,方便输出。
#include <iostream> #include <algorithm> using namespace std; struct poker { char type; int size; }; poker player[4][13];//player[0] is in south, [1] in west, [2] in north, [3] in east int char2size(const char& c) { if (c >= '2' && c <= '9') return (c - '0'); else if (c == 'A') return 14; else if (c == 'T') return 10; else if (c == 'J') return 11; else if (c == 'Q') return 12; else if (c == 'K') return 13; return -1; } char size2char(const int& c) { if (c >= 2 && c <= 9) return (c + '0'); else if (c == 14) return 'A'; else if (c == 10) return 'T'; else if (c == 11) return 'J'; else if (c == 12) return 'Q'; else if (c == 13) return 'K'; return 0; } bool comp(const poker& p1, const poker& p2) { int q1 = 0, q2 = 0; if (p1.type == 'C') q1 = 0; else if (p1.type == 'D') q1 = 1; else if (p1.type == 'S') q1 = 2; else if (p1.type == 'H') q1 = 3; if (p2.type == 'C') q2 = 0; else if (p2.type == 'D') q2 = 1; else if (p2.type == 'S') q2 = 2; else if (p2.type == 'H') q2 = 3; if (q1 != q2) return q1 < q2; else return p1.size < p2.size; } int main() { char n; while (cin >> n && n != '#') { int start = 0; if (n == 'S') start = 1; else if (n == 'W') start = 2; else if (n == 'N') start = 3; else if (n == 'E') start = 0; string order; int i = start; int p[4] = { 0,0,0,0 }; for (int r = 0; r < 2; ++r) { cin >> order; int len = order.length(); int point = 0; for (i; point < len; ) { player[i][p[i]].type = order[point++]; player[i][p[i]].size = char2size(order[point++]); p[i]++; i += 1; i %= 4; } } for (int k = 0; k < 4; ++k) { sort(player[k], player[k] + 13, comp); } for (int k = 0; k < 4; ++k) { if (k == 0) cout << "South player:" << endl; else if (k == 1) cout << "West player:" << endl; else if (k == 2) cout << "North player:" << endl; else if (k == 3) cout << "East player:" << endl; for (i = 0; i < 13; ++i) cout << '+' << '-' << '-' << '-'; cout <<'+'<< endl; for (i = 0; i < 13; ++i) { char c = size2char(player[k][i].size); cout << '|' << c << ' ' << c; } cout <<'|'<< endl; for (i = 0; i < 13; ++i) cout << '|' << ' ' << player[k][i].type << ' '; cout <<'|'<< endl; for (i = 0; i < 13; ++i) { char c = size2char(player[k][i].size); cout << '|' << c << ' ' << c; } cout << '|' << endl; for (i = 0; i < 13; ++i) cout << '+' << '-' << '-' << '-'; cout << '+' << endl; } cout << endl; } return 0; }