三个小样——C++练手(瞎倒腾)

A题——化学式区分

题目描述:

化学很神奇,以下是烷烃基。

在这里插入图片描述

假设如上图,这个烷烃基有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
是同一种,本质上就是一条链,编号其实是没有关系的,可以在纸上画画就懂了


个人思路:

其实这个题我算是取巧做的,可是说是纯数学了。大家先观察一下这五个化学方程式,找他们的异同点。首先,相同点众所周知,原子完全相同,化学键完全相同,且各自数量都一样;不同的点:每个原子的化学键不都相同,也就是说虽然化学键总数一样,但是对于个体原子来说,不都相同。
说到这里,应该都明白了,要想通过化学键区别,不能用加运算,而得用乘运算。以每个原子所有的化学键为乘数累乘(不考虑化学键重复计入)。

结果分别是:16 12 8 12 9;

观察发现,只有第二个和第四个相同,其他的具有特异性,可以区分。
说到这,我们需要一个数组num[]来保存结果。

继续看着两个相同的化学式,他们的不同在于键最多的原子是在中间还是在一端。怎么判断呢?观察,考虑在一段的原子连接的原子的化学键的和与在中间的连接的原子的化学键的和,计算,发现其具有特异性。所以我们需要一个二维数组around[a][b]来记录原子a的连接的原子。
至此,物种化学键全部具有了特异性。

那么这个问题也就解决了,代码见下~!


#include<iostream>
#include<list>
using namespace std;



int main() {

	int n;
	cin >> n;
	for (int m = 0; m < n; ++m) {
		int a, b;
		int num[7] = { 0 };
		int around[7][4] = {0};
		int sign[7] = { 0 };

		for (int i = 0; i < 5; ++i) {
			cin >> a >> b;
			num[a] ++;
			num[b] ++;
			around[a][sign[a]] = b;
			around[b][sign[b]] = a;
			sign[a]++;
			sign[b]++;

		}

		int find;
		int judge = 0;
		int mu = 1;
		for (int i = 1; i <= 6; ++i) {
			mu = mu * num[i];
		}
		if (mu == 16)
			cout << "n-hexane" << endl;
		
		else if (mu == 12)
		{
			for (find = 1; find < 7; ++find) {
				if (num[find] == 3)
					break;
			}
			for (int q = 0; q < 3; ++q) {
				judge = judge + num[around[find][q]];
			}
			if(judge == 5)
				cout << "3-methylpentane" << endl;
			else
				cout << "2-methylpentane" << endl;
		}
		
		else if (mu == 8)
			cout << "2,2-dimethylbutane" << endl;
		else if (mu == 9)
			cout << "2,3-dimethylbutane" << endl;
	}

	return 0;
}

Sample input:
输入第一行为数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b)
数据保证,输入的烷烃基是以上5种之一

				2
				1 2
				2 3
				3 4
				4 5
				5 6
				1 4
				2 3
				3 4
				4 5
				5 6

Sample output:
每组数据,输出一行,代表烷烃基的英文名

				n-hexane
				3-methylpentane

B题——大力出奇迹

题目描述:

程序设计思维作业和实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?
我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回AC,要么是返回各种其他的错误,不论是怎样的错法,它总会给你记上一笔,表明你曾经在这儿被坑过,而当你历经千辛终将它AC之后,它便会和你算笔总账,表明这题共错误提交了几次。
在岁月的长河中,你通过的题数虽然越来越多,但通过每题时你所共花去的时间(从最开始算起,直至通过题目时的这段时间)都会被记录下来,作为你曾经奋斗的痕迹。特别的,对于你通过的题目,你曾经的关于这题的每次错误提交都会被算上一定的单位时间罚时,这样一来,你在做出的题数上,可能领先别人很多,但是在做出同样题数的人中,你可能会因为罚时过高而处于排名上的劣势。
例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上了一对括号,里面有个正数b,则表示该学生AC了这道题,耗去了时间a,同时曾经错误提交了b次。例子可见下方的样例输入与输出部分。
(题目描述有点烧脑。。。。。。)


个人思路:
因为输入去全是字符穿,所以我用了string数组,为啥没用char呢。因为用char的话得用二维的数组,而string一位就能解决,虽然本质上差不多,但是能少烧点就少点咯。
这里用了两个结构体:

struct st {
	string name;
	int number;//finished 
	int score;//time score
	st() {
		number = 0;
		score = 0;
	};
	st(string n, int& num, int& s) {
		name = n;
		number = num;
		score = s;
	}
	bool operator<(const st& p)const {//重载< number降序,score升序,name字典升序
		if (number == p.number && p.score == score)
			return name > p.name;
		else
			return number != p.number ? number<p.number : p.score<score;
	}
};

struct ss {//打工用的。存输入的数据
	string name;
	string p[12];
};
st fstudent[10000];//结果数组
ss students[10000];//起始数组

基本的结构体已经有了,剩下的就是代码框架设计了。令我没想到的是,本来最简单的读入数据也花了点时间。因为起初不知道n的大小,所以不可能用一般的while(cin>>)了,所以我是这样写的:

	while (cin>>students[i].name) {//真的机智如我,哇哈哈哈,,,,
		for (int j = 0; j < n; ++j)
			cin >> students[i].p[j];
		i++;
	}

关键部分了,那么该如何统计score 和 number呢?这才是问题的关键,我是这样想的,它是以字符存进来的,那么students[].p[12]里的有效数据转化成int才能存进fstudent[].number和score里,这里我是用了强制转换(int)S- int(‘0’)转化成整形计算的。答题思路,至于细节部分,像怎么计算不同位数的字符串等等,就很简单了。

most importantly!!

你以为这样就结束了吗?nono,最关键的还是结果,对于这个题而言,输出格式是很重要的,你如果直接输出了int,那么直接AW而不会PE,所以还要把int转回string才行。
在这里,看过C++ 11刚更新的to_string()能够解决这个问题,但是奈何现在还没通用。所以退而求其次,用流输出也可以解决。

string is(int& n){//int to string
	ostringstream os;
	os << n;
	return os.str();
}

很简短的一段代码,但是没它可不行哦。

基本思路就是这样了。


代码块:

#include<iostream>
#include<string>
#include<algorithm>
#include<sstream>
#include<iomanip>
using namespace std;
struct st {
	string name;
	int number;//finished 
	int score;//time score
	st() {
		number = 0;
		score = 0;
	};
	st(string n, int& num, int& s) {
		name = n;
		number = num;
		score = s;
	}
	bool operator<(const st& p)const {
		if (number == p.number && p.score == score)
			return name > p.name;
		else
			return number != p.number ? number<p.number : p.score<score;//重载 <   number降序,score升序
	}
};

struct ss {
	string name;
	string p[12];
};
st fstudent[10000];//结果数组
ss students[10000];//起始数组


string is(int& n){//int to string
	ostringstream os;
	os << n;
	return os.str();
}


int main() {
	int n, m;
	cin >> n >> m;
	int i = 0;//学生指针

	while (cin>>students[i].name) {
		for (int j = 0; j < n; ++j)
			cin >> students[i].p[j];
		i++;
	}

	for (int k = 0; k < i; ++k) {
		fstudent[k].name = students[k].name;
		for (int j = 0; j < n; ++j) {
			if (students[k].p[j][0] != '-' && students[k].p[j][0] != '0') {//分两种情况统计score,如果是0不进行。
				fstudent[k].number++;//只要首地址存的不是 - 或者 0,题目就做完了
				if (students[k].p[j].find('(') != students[k].p[j].npos) {//当有()时
					int begin = students[k].p[j].find('('),
						end = students[k].p[j].find(')');
					for (int t = 0; t < begin; ++t) 
						fstudent[k].score = fstudent[k].score + ((int)(students[k].p[j][t]) - (int)('0')) * pow(10, begin - t - 1);
					
					for (int h = begin + 1;	h < end; ++h) 
						fstudent[k].score = fstudent[k].score + (((int)(students[k].p[j][h]) - (int)('0')) * pow(10, end - h - 1)) * m;
				}
				else {//当没有括号时
					int end = students[k].p[j].length();
					for (int h = 0; h < end; ++h)
						fstudent[k].score = fstudent[k].score + ((int)(students[k].p[j][h]) - (int)('0')) * pow(10, end - h - 1);
				}
			}
			else;
		}

	}

	sort(fstudent, fstudent + i);//这里一定要重载 < 并且根据题目要求正确重载

	for (int x = i - 1; x >= 0; --x) {
		cout << left <<setw(10) << fstudent[x].name << " "
			 << right << setw(2) << is(fstudent[x].number) << " "
			 << right << setw(4) << is(fstudent[x].score) << endl;
	}
	
	return 0;
}

C题

写不动了,下一篇~~!!见~!

略略略~~

发布了13 篇原创文章 · 获赞 0 · 访问量 222

猜你喜欢

转载自blog.csdn.net/XianAnn/article/details/104611258