week2实验
题目一:化学
问题描述
化学很神奇,以下是烷烃基。
假设如上图,这个烷烃基有6个原子和5个化学键,6个原子分别标号1~6,然后用一对数字 a,b 表示原子a和原子b间有一个化学键。这样通过5行a,b可以描述一个烷烃基
你的任务是甄别烷烃基的类别。
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的烷烃即为n-hexane
最大度数为4的烷烃即为2,2-dimethylbutane
有两个度数为3的点的烷烃即为2,3-dimethylbutane
剩余两种不好区分,需要另外判断。
我区分剩余两类的方法是判断与它们相邻的点的度数。
对于2methylpentane,它与两个度数为1的点和一个度数为2的点相邻。
对于3methylpentane,它与一个度数为1的点和两个度数为2的点相邻。
可以直接统计与它们相邻的度数为1的点的个数来区分这两类。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int c[7][7];
int main(int argc, char** argv) {
int numble;
cin>>numble;
for(int i=0;i<numble;i++)
{
for(int j=1;j<=6;j++)
for(int t=1;t<=6;t++)
{
c[j][t]=0;
}
for(int j=1;j<=5;j++)
{
int a,b;
cin>>a>>b;
c[a][b]=1;
c[b][a]=1;
}
int tem[7]={0};
int ttem[7]={0};
for(int j=1;j<=6;j++)
for(int t=1;t<=6;t++)
{
//cout<<c[j][t]<<" ";
if(c[j][t])
{
tem[j]++;
ttem[j]++;
}
}
sort(tem,tem+7);
if(tem[6]==2)
cout<<"n-hexane"<<endl;
else if(tem[6]==4)
cout<<"2,2-dimethylbutane"<<endl;
else if((tem[6]==3)&&(tem[5]==3))
cout<<"2,3-dimethylbutane"<<endl;
else
{
int one[3];//记录只连1个的原子
int three;//记录3原子
int tt=0;
for(int j=1;j<=6;j++)
{
if(ttem[j]==1)
{
one[tt]=j;
tt++;
}
else if(ttem[j]==3)
three=j;
}
//cout<<tt<<endl;
int numble=0;//记录相邻的一原子数
for(int j=1;j<=6;j++)
{
if(c[three][j]==1)
{
for(int t=0;t<3;t++)
{
if(j==one[t])
{
numble++;
break;
}
}
}
}
if(numble==2)
cout<<"2-methylpentane"<<endl;
else
cout<<"3-methylpentane"<<endl;
}
}
return 0;
}
题目二:大力出奇迹
程序设计思维作业和实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?
我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回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比较时本身就是按照字典序比较,然而当时的我并不知道这一点)、做对的题目数量、时间分。在读入时就直接把做对的题目数和时间分算出来。
读数时主要是读入那些带()的数据,我选择将数据全部作为string读入,然后找出“(”和“)”的位置,将两个符号中间的字符转化为数字。string的find方法可以较为方便的解决这个问题。
排序过程是一个简单的桶排序,先进行不重要的排序,然后一直到最重要的排序。
代码
#include <iostream>
#include <cstring>
using namespace std;
struct student{
string name;//姓名
int zidianxu;
int timu;//题目数量
int time;//时间分
student()
{
name="";
timu=0;time=0;zidianxu=0;
}
};
student s[1000];
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
int a,b;//a为题目,b为罚时
cin>>a>>b;
string tname;
int numble=0;
while(cin>>tname)
{
s[numble].name=tname;
int tsum=0;
for(int i=0;i<tname.length();i++)
{
tsum=tsum*10+int(tname[i]);
}
for(int i=0;i<a;i++)
{
string ts;
cin>>ts;
if((ts[0]=='-')||(ts[0]=='0')) continue;
int judge=ts.find("(");
if(judge==string::npos)//搜不到,一次过
{
int sum=0;
s[numble].timu++;
for(int j=0;j<ts.length();j++)
{
int tt=int(ts[j])-48;
sum=sum*10+tt;
}
s[numble].time=s[numble].time+sum;
}
else//搜到了
{
//cout<<judge<<endl;
int sum2=0;
for(int j=0;j<judge;j++)
{
int tt=int(ts[j])-48;
sum2=sum2*10+tt;
}
s[numble].time=s[numble].time+sum2;
int judge2=ts.find(")");
s[numble].timu++;
int sum=0;
for(int j=judge+1;j<judge2;j++)
{
int tt=int(ts[j])-48;
sum=sum*10+tt;
}
s[numble].time=s[numble].time+sum*b;//f罚时
}
}
numble++;
}
for(int i=0;i<numble-1;i++)
for(int j=0;j<numble-1-i;j++)
{
if(s[j].zidianxu>s[j+1].zidianxu)
{
student ttem=s[j];
s[j]=s[j+1];
s[j+1]=ttem;
}
}
for(int i=0;i<numble-1;i++)
for(int j=0;j<numble-1-i;j++)
{
if(s[j].time>s[j+1].time)
{
student ttem=s[j];
s[j]=s[j+1];
s[j+1]=ttem;
}
}
for(int i=0;i<numble-1;i++)
for(int j=0;j<numble-1-i;j++)
{
if(s[j].timu<s[j+1].timu)
{
student ttem=s[j];
s[j]=s[j+1];
s[j+1]=ttem;
}
}
for(int i=0;i<numble;i++)
{
printf("%-10s ",s[i].name.c_str());
/* for(int j=0;j<10-s[i].name.length();j++)
cout<<" ";*/
printf("%2d ",s[i].timu);
printf("%4d",s[i].time);
cout<<endl;
}
return 0;
题目三:瑞神打牌
题目描述
瑞神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|
+---+---+---+---+---+---+---+---+---+---+---+---+---+
题意解析
事实上我觉得这个题与第二题并没什么什么本质的区别:如何读入数据并把它们处理成一种比较规整的形式。同时经过简单排序后再用一种规整的形式输出。
做法
逐步分解这个问题。
首先牌有花色、数值两个属性,但为了方便比较,我令梅花的“数值”为100,方片为200以此类推把花色“换算”成数字相加后方便比较大小。同时将AJQK转化为方便比较的数字。这个过程可以用map来完成。
把牌作为结构体,令其具有花色、数值、数字三个属性(数字用于排序)。同时玩家有四名,所以可以声明一个s[4][13]的数组来存储四个玩家的手牌。
发牌过程可以利用对4取余来实现逆时针发牌。
在读入结束后,根据数字对玩家的手牌进行排序,然后按照要求输出即可。
代码
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
/*现在我们定义牌的顺序,
首先,花色是(梅花)<(方片)<(黑桃)<(红桃),
(输入时,我们用C,D,S,H分别表示梅花,方片,黑桃,红桃,即其单词首字母)。
对于牌面的值,我们规定2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。 */
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
map<char,int> pai;
map<char,int> tc;
struct card{
char huase;
char shuzi;
int numble;
card()
{
huase=' '; shuzi=' ';numble=0;
}
void p1()
{
cout<<"|"<<shuzi<<" "<<shuzi;
}
void p2()
{
cout<<"|"<<" "<<huase<<" ";
}
};
bool bijiao(card a,card b)
{
return a.numble<b.numble;
}
card s[4][13];//0 1 2 3分别为 南 西 北 东
int main(int argc, char** argv) {
pai['C']=100;
pai['D']=200;
pai['S']=300;
pai['H']=400;
pai['2']=1;
pai['3']=2;
pai['4']=3;
pai['5']=4;
pai['6']=5;
pai['7']=6;
pai['8']=7;
pai['9']=8;
pai['T']=9;
pai['J']=10;
pai['Q']=11;
pai['K']=12;
pai['A']=13;
tc['S']=0;
tc['W']=1;
tc['N']=2;
tc['E']=3;
string d[4]={"South player:","West player:","North player:","East player:"};
char head;
while(cin>>head)
{
if(head=='#') break;
int numble=tc[head]+1;
int shu=0;//记录每个牌手手里的牌数
for(int i=0;i<52;i++)
{
char a,b;
cin>>a>>b;
int tem=pai[a]+pai[b];//排序大小
s[numble%4][shu].huase=a;
s[numble%4][shu].shuzi=b;
s[numble%4][shu].numble=tem;
numble++;
if((i+1)%4==0)
{
shu++;
}
}
for(int i=0;i<4;i++)
sort(s[i],s[i]+13,bijiao);
for(int i=0;i<4;i++)
{
cout<<d[i]<<endl;
cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
for(int j=0;j<13;j++)
{
s[i][j].p1();
}
cout<<"|"<<endl;
for(int j=0;j<13;j++)
{
s[i][j].p2();
}
cout<<"|"<<endl;
for(int j=0;j<13;j++)
{
s[i][j].p1();
}
cout<<"|"<<endl;
cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
}
cout<<endl;
}
return 0;
}
上一篇: URL编码的一些思考
下一篇: uniapp 条件渲染