欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

week2实验

程序员文章站 2022-07-12 14:57:54
...

题目一:化学

问题描述

化学很神奇,以下是烷烃基。
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;
}