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
题目思路:
通过观察我们可以发现首先可以根据每个图中节点的度数为某个值的节点数量来区别不同的烷烃基。但是这样的话我们无法区分2-methylpentane和3-methylpentane,这两个烷烃基的区分可以使用度数为三的节点邻接点的度数之和可以区分。所以在该题中我使用link结构体类型存放两个连接的节点,使用count数组存放各个节点的度数。
struct link{ //相连接的节点
int a;
int b;
};
代码实现:
#include <iostream>
using namespace std;
//const int hex[] = {0 , 2 , 4 , 0 , 0};
//const int meth2[] = {0 , 3 , 2 , 1 , 0};
//const int meth3[] = {0 , 3 , 2 , 1 , 0};
//const int dim3[] = {0 , 4 , 0 , 2 , 0};
//const int dim2[] = {0 , 4 , 1 , 0 , 1};
struct link{ //连接节点
int a;
int b;
};
int main()
{
int n;
cin >> n;
link v[5]; //存放输入
int count[7]; //存放各个节点的度数
int num2 = 0;
for(int i = 0; i < n; i++)
{
num2 = 0;
for(int i = 0; i < 7; i++)
count[i] = 0;
for(int j = 0; j < 5; j++)
{
cin >> v[j].a >> v[j].b;
count[v[j].a]++;
count[v[j].b]++;
}
for(int j = 1; j < 7; j++)
if(count[j] == 2) //度数为2的节点
num2++; //度数为2的节点个数
int x = 0;
switch(num2)
{
case 0:cout << "2,3-dimethylbutane" << endl;break;
case 1:cout << "2,2-dimethylbutane" << endl;break;
case 4:cout << "n-hexane" << endl;break;
case 2:
for(int r = 0; r < 5; r++)
{
if(count[v[r].a] == 3 || count[v[r].b] == 3) //度数为3的节点
{
x = x + count[v[r].a] + count[v[r].b]; //求度数为3的节点及其邻接点的度数之和
}
}
if(x == 13) cout << "2-methylpentane" << endl;
else if(x == 14) cout << "3-methylpentane" << endl;
break;
}
}
}
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
题目思路:
这道题主要的考察点使字符串的处理,根据输入中会穿插空格,并且每行的输入不会超过十三个,这样我们就可以直接定义一个长度为十三的string数组,用来存放输入的每行的字符串。
第一个字符串是学生的名字,之后的字符串需要分有括号和无括号分别处理。如果没有括号,需要判断为正数还是负数,如果是整数则将该同学AC的题目数量加一,并将这个整数值加到时间分中,负数则不需要任何操作。如果有括号则将该同学AC的题目数量加一,并将括号外面的数直接加到时间分中,括号里面的数字乘以单位罚时加到时间分中。其中我们使用了atoi函数将字符串转化为数字。
最后再将所有的人按照AC题目的数量升序排列,时间分降序排列。
在结果输出的时候,使用std::right,std::left进行对齐处理,使用setw函数规范宽度。
实现代码:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <utility>
#include <algorithm>
#include <iomanip>
using namespace std;
struct STU //每个人的信息和成绩
{
string name; //姓名
int num; //AC题目的数量
int time; //时间分
bool operator < (const STU &p) const{
if(num != p.num) return num > p.num;
if(time != p.time) return time < p.time;
return name < p.name;
}
};
int main()
{
int n,m;
vector<string> str(13); //输入的字符串
vector<STU> s;
cin >> n >> m;
int i = 0;
STU st;
while(cin>>str[0]) //姓名
{
st.num = 0;
st.time = 0;
for(int j = 1; j <= n; j++)
cin >> str[j];
st.name = str[0];
for(int j = 1; j <= n; j++)
{
if(str[j].find('(') == string::npos) //不包含括号
{
if(atoi(str[j].c_str()) > 0)
{
st.num++;
st.time += atoi(str[j].c_str());
}
}
else{ //包含括号
st.num++;
string A,B;
int local;
for(int k = 0; k < str[j].size(); k++)
{
if(str[j][k] == '(')
{
A = str[j].substr(0,k); //括号前面的字符串
local = k+1;
}
if(str[j][k] == ')')
B = str[j].substr(local,k-local);//括号中间的字符串
}
st.time += (atoi(A.c_str()) + atoi(B.c_str()) * m);
}
}
s.push_back(st);
i++;
}
sort(s.begin(),s.end());
for(int y = 0; y < i;y++)
{
cout << std::left << setw(10) << s[y].name << " " << std::right << setw(2) << s[y].num << " " << std::right << setw(4) << s[y].time<<endl;
}
}
C-瑞神打牌(不支持C++11,G++和C++编译器都试试提交哈)
题目描述:
瑞神HRZ因为疫情在家闲得无聊,同时他又非常厉害,所有的课对他来说都是水一水就能拿A+,所以他无聊,找来了另外三个人:咕咕东,腾神以及zjm来打牌(天下苦瑞神久矣)。
显然,牌局由四个人构成,围成一圈。我们称四个方向为北 东 南 西。对应的英文是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|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
题目思路:
在该题目中我定义了一个结构体类型Brand,其中包含表示花色,数值和持牌人方向的三个字符型变量。首先我们需要根据发牌人来计算出发牌的顺序,在这里我是使用了一个队列,每次判断队为元素是否为发牌人,如果不是则将队首元素弹出并插入队尾,即循环队列。这样就可以确定发牌顺序了。然后定义一个Brand类型的数组存放所有的牌的信息和持牌人的信息。
这里在对花色和数值的比较中我是定义了Brand类型内部的函数,转化为int类型比较,并重载了<运算符。
最后使用sort函数对持牌人方向按照南西北东排序,花色和数值按照大小排序并输出。
代码实现
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <utility>
#include <queue>
#include <algorithm>
#include <iomanip>
using namespace std;
//东南西北方向的玩家
const string EP = "East player";
const string SP = "South player";
const string WP = "West player";
const string NP = "North player";
//花色
struct Brand{
char c; //花色
char num;//数值
char dir;//方向
int color_cmp()const //花色比较转换
{
if(c == 'C') return 1;
else if(c == 'D') return 2;
else if(c == 'S') return 3;
else return 4;
}
int num_cmp()const //数值比较
{
if(num == 'T') return 10;
else if(num == 'J') return 11;
else if(num == 'Q') return 12;
else if(num == 'K') return 13;
else if(num == 'A') return 14;
else return num - '0';
}
int dir_cmp()const //输出方向顺序
{
if(dir == 'S') return 0;
else if(dir == 'W') return 1;
else if(dir == 'N') return 2;
else return 4;
}
bool operator < (const Brand& s) const
{
if(dir != s.dir) return this->dir_cmp() < s.dir_cmp();
if(c != s.c) return this->color_cmp() < s.color_cmp(); //花色升序
return this->num_cmp() < s.num_cmp(); //数值升序
}
};
queue<char> order; //发牌顺序
Brand vb[52];
void initi_order() //order的初始化
{
order.push('E');
order.push('S');
order.push('W');
order.push('N');
}
void update_order(char ch) //更新发牌顺序
{
while(order.back() != ch)
{
char d = order.front();
order.pop();
order.push(d);
}
}
void output() //输出
{
cout << "South player:" <<endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
for(int i = 0; i < 13; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
for(int i = 0; i < 13; i++)
{
cout << "|" << " " << vb[i].c << " " ;
}
cout << "|" << endl;
for(int i = 0; i < 13; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
cout << "West player:" <<endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
for(int i = 13; i < 26; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
for(int i = 13; i < 26; i++)
{
cout << "|" << " " << vb[i].c << " " ;
}
cout << "|" << endl;
for(int i = 13; i < 26; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
cout << "North player:" <<endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
for(int i = 26; i < 39; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
for(int i = 26; i < 39; i++)
{
cout << "|" << " " << vb[i].c << " " ;
}
cout << "|" << endl;
for(int i = 26; i < 39; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
cout << "East player:" <<endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
for(int i = 39; i < 52; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
for(int i = 39; i < 52; i++)
{
cout << "|" << " " << vb[i].c << " " ;
}
cout << "|" << endl;
for(int i = 39; i < 52; i++)
{
cout << "|" << vb[i].num << " " << vb[i].num ;
}
cout << "|" << endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl << endl;
}
int main()
{
char ch; //发牌人
char c1,c2;
initi_order(); //初始化
while(cin >> ch)
{
char o[4]; //存储发牌顺序的数组
Brand b;
if(ch == '#') {cout<<endl; break;}
update_order(ch);
for(int i = 0; i < 4; i++) //确定发牌顺序
{
o[i] = order.front();
order.pop();
order.push(o[i]);
}
for(int i = 0;i < 52; i++)
{
cin >> c1 >> c2;
b.c = c1;
b.num = c2;
b.dir = o[i%4];
vb[i] = b;
}
sort(vb,vb+52);
output();
}
}