程序设计思维与实践 Week2 实验 (3/4/数据班)

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

思路

通过观察,可以发现不同烷烃基的点的度数不同:
n-hexane:两个一度定点,四个二度顶点
2,3-dimethylbutane:四个一度顶点,两个三度顶点
2,2-dimethylbutane:四个一度顶点,一个二度顶点,一个四度顶点
2-methylpentane:三个一度顶点,两个二度顶点,一个三度顶点,其中与三度定点相连的为两个一度顶点和一个二度顶点
3-methylpentane:与2-methylpentane一致,其中与三度顶点相连的为两个一度顶点和一个二度顶点

首先统计烷烃基各点的度数,若为前三种,直接判断输出即可,若不是,则根据与三度节点相连的节点的度数判断即可。

实现代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

bool edge[7][7]={false};
int num[7]={0};
int main()
{
	int n;
	cin>>n;
	int a,b;
	int x1=0,x2=0,x3=0,x4=0;
	int mark;
	for(int i=0;i<n;i++)
	{
		x1=0,x2=0,x3=0,x4=0;
		for(int p=0;p<7;p++)
		{
			num[p]=0;
			for(int q=0;q<7;q++)
				 edge[p][q]=false;
		}
		for(int j=0;j<5;j++)
		{
			cin>>a>>b;
			edge[a][b]=true;
			edge[b][a]=true;
			num[a]++,num[b]++;
		}
		for(int k=1;k<=6;k++)
		{
			if(num[k]==1) x1++;
			else if(num[k]==2) x2++;
			else if(num[k]==3) 
			{
				x3++;
				mark=k;
			}
			else if(num[k]==4) x4++;
		}
		if(x1==2&&x2==4) cout<<"n-hexane"<<endl;
		else if(x1==4&&x3==2) cout<<"2,3-dimethylbutane"<<endl;
		else if(x1==4&&x2==1&&x4==1) cout<<"2,2-dimethylbutane"<<endl;
		else if(x1==3&&x2==2&&x3==1)
		{
			int y1=0,y2=0;
			for(int s=1;s<=6;s++)
			{
				if(edge[mark][s]==true&&edge[s][mark]==true)
				{
					if(num[s]==1) y1++;
					if(num[s]==2) y2++;
				}
			}
			if(y1==1&&y2==2) cout<<"3-methylpentane"<<endl;
			if(y1==2&&y2==1) cout<<"2-methylpentane"<<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

思路

使用结构体记录每个学生的信息:用户名、AC数、罚时,然后通过多关键字排序,按序输出每个学生的信息。这道题的重点在于对字符串的处理:我是采用scanf读取的数据个数来判断的:

if(scanf("%d(%d)",&c,&d)==2)
	{
		st[i].ac++;
		st[i].time+=c+d*m;
	}

也可以使用助教所说的方法,使用sscanf来进行判断:

scanf("%s",s);
if(sscanf(s,"%d(%d)",&c,&d)==2)

总结

字符串的处理:scanf和sscanf的妙用

实现代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

struct p{
	char name[15];
	int ac;
	int time;
	bool operator < (const p &a)
	{
		if(ac!=a.ac) return ac>a.ac;
		if(time!=a.time) return time<a.time;
		return strcmp(name,a.name)<0;
	}
}st[10005];


int main()
{
	int n,m;
	cin>>n>>m;
	int i=0;
	int num=0;
	int c,d;
	while(scanf("%10s",st[i].name)!=EOF)
	{
		st[i].ac=0,st[i].time=0;
		for(int j=0;j<n;j++)
		{
			if(scanf("%d(%d)",&c,&d)==2)
			{
				st[i].ac++;
				st[i].time+=c+d*m;
			}
			else{
				if(c>0)
				{
					st[i].ac++;
					st[i].time+=c;
				}
			}
		}
		i++;
	}
	sort(st,st+i);
	for(int j=0;j<i;j++)
	{
		printf("%-10s %2d %4d\n",st[j].name,st[j].ac,st[j].time);
	}
	return 0;
}

C - 瑞神打牌 (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|
±–±--±–±--±–±--±–±--±–±--±–±--±–+

思路

利用结构体保存牌的花色和数字,通过该结构体的vector数组来表示玩家和玩家手中的牌,然后模拟发牌,将牌存放到数组中,通过玩家顺序以及结构体的多关键字排序,按序输出各玩家手中的牌。

补充

  1. printf中左对齐:%-10d,右对齐%:10d,什么都不加%d默认左对齐
  2. 对花色和数字的区分,一开始使用了map,出现TLE,可能是oj的编译器有些古老,导致STL优化不到位造成的
  3. OLE的原因:vector数组使用完未清空。因为样例只有一组,不清空也看不出来,调了好长时间(ㄒoㄒ)

实现代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int color(char c)//区分花色
{
	if(c=='C') return 0;
	if(c=='D') return 1;
	if(c=='S') return 2;
	if(c=='H') return 3;
}
int number(char c)//区分数字
{
	if (c=='A') return 14;
	if (c=='K') return 13;
	if (c=='Q') return 12;
	if(c=='J') return 11;
	if(c=='T') return 10;
	return c-'0';
}
char s[10005];
struct p{
	char col;
	char num;
	bool operator < (const p &cur)
	{
		if(color(col)!=color(cur.col)) return color(col)<color(cur.col);
		if(number(num)!=number(cur.num)) return number(num)<number(cur.num); 
	}
};
vector<p> men[4];

int main()
{
	int q=0;
	int order=-1;
	while (scanf("%s",s)!=EOF)
	{
		if(s[0]=='#') break;
		else if(s[0]=='E') order=0;
		else if(s[0]=='S') order=1;
		else if(s[0]=='W') order=2;
		else if(s[0]=='N') order=3;
		if(q!=0) printf("\n");
		else q=1;
		for(int i=0;i<4;i++) men[i].clear();
		scanf("%s",s),scanf("%s",s+52);
		for(int i=0;i<104;i=i+2,order=(order+1)%4)
		{
			p cur;
			cur.col=s[i],cur.num=s[i+1];
			men[order].push_back(cur);
		}
		for(int i=0;i<4;i++) sort(men[i].begin(),men[i].end());
		for(int i=0;i<4;i++)
		{
			if(i==0) printf("South player:\n");
			if(i==1) printf("West player:\n");
			if(i==2) printf("North player:\n");
			if(i==3) printf("East player:\n");
				printf("+---+---+---+---+---+---+---+---+---+---+---+---+---+\n");
				for(int j=0;j<men[i].size();j++)
				{
					printf("|%c %c",men[i][j].num,men[i][j].num);
					if(j==men[i].size()-1) printf("|\n");
				}
				for(int j=0;j<men[i].size();j++)
				{
					printf("| %c ",men[i][j].col);
					if(j==men[i].size()-1) printf("|\n");
				}
				for(int j=0;j<men[i].size();j++)
				{
					printf("|%c %c",men[i][j].num,men[i][j].num);
					if(j==men[i].size()-1) printf("|\n");
				}
				printf("+---+---+---+---+---+---+---+---+---+---+---+---+---+\n");
		}	
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值