「程序设计思维与实践」Week2 实验:暴力专场

A - 化学 (编译器选 GNU G++) Gym - 270437A

Description

化学很神奇,以下是烷烃基。
在这里插入图片描述
假设如上图,这个烷烃基有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

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

Sample Input

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

题解

刚开始还考虑建图做,后来一想我就5个点,我稍微遍历一下就能拿到这张图的所有信息。
观察5种图形,把每幅图的节点的5个度数从小到大排序,可以发现如下规律:

// 1 1 2 2 2 2    n-hexane
// 1 1 1 2 2 3    2-methylpentane 3点为有2个1点的
// 1 1 1 2 2 3    3-methylpentane
// 1 1 1 1 3 3    2,3-dimethylbutane
// 1 1 1 1 2 4    2,2-dimethylbutane

因此只靠度数便可以区分第1 4 5 种。然后再来找2和3的不同点:
观察图形可知,两颗树3度节点的位置不同(其实也就是直径不同),第2个图中3度节点链接向1个2度节点,2个1度节点,第2个图中3度节点链接向2个2度节点,1个1度节点,根据这个特性判断哪个是第二种哪个是第三种就可了。

代码

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

int main() {
	int T;
	cin >> T;
	while(T --) {
		pair<int,int> edges[10];
		int ans[10];
		for(int i = 1; i <= 5; ++ i) {
			scanf("%d%d", &edges[i].first, &edges[i].second);
		}
		for(int i = 1; i <= 6; ++ i) {
			ans[i] = 0;
			for(int j = 1; j <= 5; ++ j) {
				if(edges[j].first == i || edges[j].second == i)
					ans[i] ++;
			}
		}
		sort(ans+1, ans+7);
		if(ans[6] == 4) {
			puts("2,2-dimethylbutane");
		} else if(ans[5] == 3) {
			puts("2,3-dimethylbutane");
		} else if(ans[3] == 2) {
			puts("n-hexane");
		} else {
			int m3, m2_1 = -1, m2_2 = -1;
			for(int i = 1; i <= 6; ++ i) {
				ans[i] = 0;
				for(int j = 1; j <= 5; ++ j) {
					if(edges[j].first == i || edges[j].second == i)
						ans[i] ++;
				}
				if(ans[i] == 3) m3 = i;
				if(ans[i] == 2 && m2_1 == -1) m2_1 = i;
				if(ans[i] == 2 && m2_1 != -1) m2_2 = i;
			}
			// cout << m3 << " " << m2_1 << " " << m2_2 << endl;
			bool flag1 = false; 
			bool flag2 = false;
			for(int i = 1; i <= 5; ++ i) {
				if(edges[i].first == m3 && edges[i].second == m2_1) {
					flag1 = true;
				}
				if(edges[i].first == m2_1 && edges[i].second == m3) {
					flag1 = true;
				}
				if(edges[i].first == m3 && edges[i].second == m2_2) {
					flag2 = true;
				}
				if(edges[i].first == m2_2 && edges[i].second == m3) {
					flag2 = true;
				}
			}
			if(flag1 && flag2) {
				puts("3-methylpentane");
			} else {
				puts("2-methylpentane");
			}

		}
	}
	return 0;
}

B - 爆零(×)大力出奇迹(√) HDU - 2093

Description

程序设计思维作业和实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?
我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回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

题解

根据刚开始给出的题目数量来依次读入每个人的每个题,对于读入的每个题的状态字符串,按照以下逻辑进行处理:
先检查第一个字符是否是-0,因为这代表没有通过这道题,我们不进行处理。
如果不是以上情况,通过题目个数++,然后查找(,如果没有,代表没有罚时,直接将字符串处理成数字加入时间,如果有那么有罚时,除了加入通过时间,还要处理括号内的数字,乘m加入时间。
最终将处理的每个人加入一个结构体类型中,按照题意关键字大小排序,输出即可。
注意输出格式:可以用std::left来调整左右对齐,setw(10)来控制宽度。

代码

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

int tot = 0;
struct PERSON{
	string name;
	int acs;
	int time;
	bool operator < (const PERSON& a) const {
		if(acs != a.acs) return acs > a.acs;
		if(time != a.time) return time < a.time;	
		return name < a.name;
	}
}person[100010];

//40(3) 96
int main() {
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	int n, m;
	cin >> n >> m;
	while(cin >> person[++tot].name) {
		person[tot].acs = person[tot].time = 0;
		for(int i = 1; i <= n; ++ i) {
			string s;
			cin >> s;
			if(s[0] == '-' || s[0] == '0') {
				continue;
			} else {
				person[tot].acs ++;
			}

			int left = s.find('(');
			// cout << left << "((((" << endl;
			if(left != s.npos) { // 有罚时
				int right = s.find(')');
				int x = 0;
				for(int i = left+1; i <= right-1; ++ i) {
					x += s[i]-'0';
					x *= 10;
				}
				x /= 10;
				person[tot].time += m*x;
				// cout << "***" << m*x << endl;
				x = 0;
				for(int i = 0; i <= left-1; ++ i) {
					x += s[i]-'0';
					x *= 10;
				}
				x /= 10;
				person[tot].time += x;
				// cout << "(()))())" << x << endl;
			} else {
				int x = 0;
				int len = s.length();
				for(int i = 0; i <= len-1; ++ i) {
					x += s[i]-'0';
					x *= 10;
				}
				x /= 10;
				person[tot].time += x;
				// cout << "TTTT@@@" << x << endl;
			}
		}
		// cout << person[tot].name << " " << person[tot].acs << " " << person[tot].time << endl;
	}
	sort(person+1, person+tot+1);
	for(int i = 1; i <= tot; i++) {
		if(person[i].name.length()) {
			cout << std::left
				<< setw(10) << person[i].name << " "
				<< std::right
				<< setw(2) << person[i].acs << " "
				<< std::right
				<< setw(4) << person[i].time
				<< endl;
		}
	}

	return 0;
}

C - 瑞神打牌 (不支持C++11,G++和C++编译器都试试提交哈) POJ - 1786

Description

瑞神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|
+---+---+---+---+---+---+---+---+---+---+---+---+---+

题解

创建「牌」结构体,存储初始52张牌的花色和大小。
将SWNE四个方向建立编号1234,然后利用map建立发牌人和对应第几张的归属的映射:

如果发牌人是3,那么从4开始,S对应的是第二张牌
以此类推
// if 3 start 4 s=2
// if 4 start 1 s=1
// if 1 start 2 s=4
// if 2 start 3 s=3

知道了S是第几张牌,剩下的只需要加上一个变量即可全部算出。
再建立一个4*13的扑克牌结构体数组来存储结果:

for(int j = 0; j < 4; ++ j){
			for(int i = 0; i <= 12; ++ i) {
				int x = (i*4+cx[m[holder[0]]]+j)%52;
				if(!x) x = 52;
				p[j+1][i+1] = peck[x];
			}
		}

最后每个人加个排序,按照格式输出即可。

代码

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

map<char,char> daxiao;
map<char,char> huase;

struct pppeck{
	char hs;
	char num;
	bool operator < (const pppeck &a) const {
		if(hs != a.hs) return huase[hs] < huase[a.hs];
		return daxiao[num] < daxiao[a.num];
	}
}peck[233];

pppeck p[10][20];

//  S W N E S W N E
//  1 2 3 4 1 2 3 4
// if 3 start 4 s=2
// if 4 start 1 s=1
// if 1 start 2 s=4
// if 2 start 3 s=3
map<char,int> m;
int cx[10];

void init() {
	m['S'] = 1;m['W'] = 2;m['N'] = 3;m['E'] = 4;
	cx[3] = 2;cx[4] = 1;cx[1] = 4;cx[2] = 3;
	for(char i = '2'; i <= '9'; i = i+1) {
		daxiao[i] = i;
	}
	daxiao['T'] = 'a';
	daxiao['J'] = 'b';
	daxiao['Q'] = 'c';
	daxiao['K'] = 'd';
	daxiao['A'] = 'e';
	huase['C'] = '1';
	huase['D'] = '2';
	huase['S'] = '3';
	huase['H'] = '4';
}

void init2() {
	for(int i = 1; i <= 52; ++i) {
		peck[i].num = peck[i].hs = '0';
	}
	for(int i = 1; i <= 4; ++i) {
		for(int j = 1; j <= 13; ++j) {
			p[i][j].num = p[i][j].num = '0';
		}
	}
}

int main() {
	// freopen("in.txt","r",stdin);
	init();

	string holder;
	while(cin >> holder) {
		if(holder[0] == '#') {
			break;
		} else {
			init2();
		}
		int tot = 0;
		string l,l2;
		cin >> l;
		for(int i = 0; i < 52; i += 2) {
			peck[++tot].hs = l[i];
			peck[tot].num = l[i+1];
		}
		cin >> l2;
		for(int i = 0; i < 52; i += 2) {
			peck[++tot].hs = l2[i];
			peck[tot].num = l2[i+1];
		}
		// 1 2 3 4 .....51 52 53 54
		// 1 2 3 4 .....51 0  1  2%52
		// 1 2 3 4 .....51 52 0  1
		// 1 2 3 4 .....51 52 1  2

		for(int j = 0; j < 4; ++ j){
			for(int i = 0; i <= 12; ++ i) {
				int x = (i*4+cx[m[holder[0]]]+j)%52;
				if(!x) x = 52;
				p[j+1][i+1] = peck[x];
			}
		}
		sort(p[1]+1,p[1]+14);
		sort(p[2]+1,p[2]+14);
		sort(p[3]+1,p[3]+14);
		sort(p[4]+1,p[4]+14);
		for (int i = 1; i <= 4; ++ i) {
			if (i == 1) {
				puts("South player:");
			} else if (i == 2) {
				puts("West player:");
			} else if (i == 3) {
				puts("North player:");
			} else if (i == 4) {
				puts("East player:");
			}
			puts("+---+---+---+---+---+---+---+---+---+---+---+---+---+");
			cout << "|";
			for(int j = 1; j <= 13; ++ j) {
				cout << p[i][j].num << " " << p[i][j].num << "|";
			}
			cout << endl << "|";
			for(int j = 1; j <= 13; ++ j) {
				cout << " " << p[i][j].hs << " |";
			}
			cout << endl << "|";
			for(int j = 1; j <= 13; ++ j) {
				cout << p[i][j].num << " " << p[i][j].num << "|";
			}
			cout << endl;
			puts("+---+---+---+---+---+---+---+---+---+---+---+---+---+");
		}
		cout << endl;
	}


	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值