程序设计思维实验 week2
整体感受
感觉实验题目难度挺合适,有点挑战性却又不是特别困难。三道题整体用时大约5个多小时,其中有很大部分卡在了B题疯狂报PE上。
三道题都是小模拟题,感觉个人解题的时候关键在于如何区分出不同的情况以便进行不同的后续操作(输出)。区分的时候需要仔细观察题目sample输入的特征。
Problem A
1.题目概述
假设如下图,这个烷烃基有6个原子和5个化学键,6个原子分别标号1~6,然后用一对数字 a,b 表示原子a和原子b间有一个化学键。这样通过5行a,b可以描述一个烷烃基。
你的任务是甄别烷烃的类别。
2.Input
输入第一行为数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b)
数据保证,输入的烷烃基是以上5种之一。
3.Output
每组数据,输出一行,代表烷烃基的英文名。
4.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
5.整体解题思路
分辨不同烷烃的主要依据是每个原子上接的化学键个数。例n-hexane有四个接了两个化学键的原子,两个接了一个化学键的原子。同理,2,3 和2,2 型烷烃也有唯一标示特征。如果是methylpentane,首先找到接了三个化学键的原子,然后判断与该原子相连的原子所接的化学键个数,若有两个只接了一个化学键的原子则为2-methylpentane,否则为3-methylpentane。
6.代码
#include <iostream>
using namespace std;
//设置point 类储存原子
class point
{
public:
point()
{
num=0;
nlink=0;
p=new int[4];
}
void link(point* n)
{
p[nlink]=n->num;
nlink++;
}
public:
int num=0;//原子序号
int nlink=0;//原子接的化学键个数
int *p;//相连原子的序号
};
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
point* q;
q=new point[6];
for(int j=0;j<6;j++)
{
q[j].num=j+1;
}
//原子与原子之间进行连接
for(int j=0;j<5;j++)
{
int m1,m2;
cin>>m1;
cin>>m2;
point* p1=&q[m1-1];
point* p2=&q[m2-1];
q[m1-1].link(p2);
q[m2-1].link(p1);
}
//分别计算含有2,3,4个化学键的原子个数
int tw=0,th=0,fo=0;
int pth=0;
for(int j=0;j<6;j++)
{
if(q[j].nlink==2)
tw++;
else if(q[j].nlink==3)
{
th++;
pth=j;
}
else if(q[j].nlink==4)
fo++;
}
//有唯一标示的情况可以直接判定输出
if(tw==4)
cout<<"n-hexane"<<endl;
else if(th==2)
cout<<"2,3-dimethylbutane"<<endl;
else if(fo==1)
cout<<"2,2-dimethylbutane"<<endl;
//如果为3
else if(th==1)
{
int tmp=0;
for(int j=0;j<3;j++)
{
int t=q[pth].p[j]-1;
if(q[t].nlink==1)
tmp++;
}
if(tmp==1)
cout<<"3-methylpentane"<<endl;
else
cout<<"2-methylpentane"<<endl;
}
}
return 0;
}
Problem B
1.题目概述
模拟题目评测系统。例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上了一对括号,里面有个正数b,则表示该学生AC了这道题,耗去了时间a,同时曾经错误提交了b次。例子可见下方的样例输入与输出部分。
2. Input
输入数据包含多行,第一行是共有的题数n(1≤n≤12)以及单位罚时m(10≤m≤20),之后的每行数据描述一个学生的信息,首先是学生的用户名(不多于10个字符的字串)其次是所有n道题的得分现状,其描述采用问题描述中的数量标记的格式,见上面的表格。
3.Output
根据这些学生的得分现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出
4.Example
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
Output
TT 5 348
yjq 4 342
GuGuDong 3 197
hrz 3 256
Zjm 2 316
OMRailgun 0 0
5.整体思路
首先观察输入信息,每个题的做题情况如果第一个字符是‘-’或‘0‘可以不用管,继续读取下一道题的做题情况。其他情况的话首先做出题数+1,再判断是否有’(‘,如果没有直接将字符转化为数值存进time,如果有再找到’)‘,将中间的字符转化为数值加进time。多值排序时才用冒泡法。
6.代码
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<iomanip>
using namespace std;
//将字符变为数值
int change(string s)
{
int size=s.size();
int result=0;
for(int i=0;i<size;i++)
{
int m=s[i]-48;
result+=(m*pow(10,size-i-1));
}
return result;
}
//member记录每位参赛者
class member
{
public:
member()
{}
member(string name,int n,int penalty)
{
_n=n;
_penalty=penalty;
_name.append(name);
}
void addscore()
{
for(int i=0;i<_n;i++) {
int target1 = 0, target2 = 0;
string s;
cin >> s;
if (s[0] == '-' || s[0] == '0') continue;
else {
score++;
for (int j = 0; j < s.size(); j++)
{
if (s[j] == '(') target1 = j;
}
if (target1 == 0) {
time += change(s);
}
else {
string s1(s, 0, target1);
string s2(s, target1 + 1);
s2.pop_back();
time += change(s1);
time += _penalty * change(s2);
}
}
}
}
inline bool operator < (const member &x) const
{
if((score>x.score)
||((score==x.score)&&(time<x.time))
||((score==x.score)&&(time==x.time)&&(_name[0]<x._name[0])))
return true;
else
return false;
}
public:
int _n;
int _penalty;
string _name;
int score=0;
int time=0;
};
int main() {
int n, penalty;
cin >> n;
cin >> penalty;
vector<member> MemberList;
string name;
int tmp=0;
while (cin >> name) {
if(cin.get()=='\n') break;
member P(name, n, penalty);
P.addscore();
MemberList.push_back(P);
tmp++;
}
sort(&MemberList,&MemberList+tmp);
for(int i=0;i<MemberList.size();i++)
{
cout<<left<<setw(10)<<MemberList[i]._name<<' '<<right<<setw(2)<<MemberList[i].score<<' '<<right<<setw(4)<<MemberList[i].time<<endl;
}
return 0;
}
Problem C
写了4800+length的题…(我也很无奈啊
1.问题描述
模拟四个人打扑克摸牌并排序的过程。
游戏一共由一副扑克,也就是52张构成。开始,我们指定一位发牌员(东南西北中的一个,用英文首字母标识)开始发牌,发牌顺序为顺时针,发牌员第一个不发自己,而是发他的下一个人(顺时针的下一个人)。这样,每个人都会拿到13张牌。
定义牌的顺序,首先,花色是(梅花)<(方片)<(黑桃)<(红桃),(输入时,我们用C,D,S,H分别表示梅花,方片,黑桃,红桃,即其单词首字母)。对于牌面的值,我们规定2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。
要求从小到大排序每个人手中的牌,并按照给定格式输出。
2.Input
输入包含多组数据
每组数据的第一行包含一个大写字符,表示发牌员是谁。如果该字符为‘#’则表示输入结束。
接下来有两行,每行有52个字符,表示了26张牌,两行加起来一共52张牌。每张牌都由两个字符组成,第一个字符表示花色,第二个字符表示数值。
3.Output
每组数据应该由24行的组成,输出按照顺时针方向,始终先输出South Player的结果,每位玩家先输出一行即玩家名称(东南西北),接下来五行,第一行和第五行输出固定格式(见样例),第二行和第四行按顺序和格式输出数值(见样例),第三行按顺序和格式输出花色(见样例)。
4.Example
Input
N
CTCAH8CJD4C6D9SQC7S5HAD2HJH9CKD3H6D6D7H3HQH4C5DKHKS9
SJDTS3S7S4C4CQHTSAH2D8DJSTSKS2H5D5DQDAH7C9S8C8S6C2C3
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|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
5.整体思路
首先对每个玩家的牌进行录入,为了区分不同的花色,对C D S H四种花色分别设置0,100,200,300的附加值,加在卡牌本身数值上,用于排序时候比较大小。
在指定一名玩家后,计算与south的偏差值(weight),南西北东分别设置为3 2 1 0;进行输出时,第i次输出的是第(i+weight)%4 卡牌组。
6.代码
#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
class cards
{
public:
cards()
{
_Pval='C';
_val=0;
_addition=0;
_variety='C';
waterfall=0;//记录用于排序时的权值
}
cards(char addition,char val)
{
//设置数值
_Pval=val;
//设置花色
_variety=addition;
//根据花色设置附加值
switch(addition) {
case 'C': {
_addition = 0;
break;
}
case 'D': {
_addition = 100;
break;
}
case 'S': {
_addition = 200;
break;
}
case 'H': {
_addition = 300;
break;
}
default : break;
}
//将字符转换成数值
if(val>=50&&val<=57)//2-9
{
_val=val-48;
}
else
{
switch(val) {
case 'T': {
_val = 10;
break;
}
case 'J': {
_val = 11;
break;
}
case 'Q': {
_val = 12;
break;
}
case 'K': {
_val = 13;
break;
}
case 'A': {
_val = 14;
break;
}
default : break;
}
}
//计算waterfall用于排序计算
waterfall=_val+_addition;
}
inline bool operator < (const cards &x) const
{
return waterfall>x.waterfall;
}
public:
int _val;
int _addition;
int waterfall;
char _variety;
char _Pval;
};
void Vsort(int k,vector<cards> &List)
{
sort(&List,&List+13);
switch(k)
{
case 0:
{
cout << "South player:" << endl;
break;
}
case 1:
{
cout << "West player:" << endl;
break;
}
case 2:
{
cout << "North player:" << endl;
break;
}
case 3:
{
cout << "East player:" << endl;
break;
}
default: break;
}
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
for (int j = 0; j < 13; j++)
{
cout << "|" << List[j]._Pval << ' ' << List[j]._Pval;
}
cout << '|' << endl;
for (int j = 0; j < 13; j++) {
cout << "|" << ' ' << List[j]._variety << ' ';
}
cout << '|' << endl;
for (int j = 0; j < 13; j++) {
cout << "|" << List[j]._Pval << ' ' << List[j]._Pval;
}
cout << '|' << endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
}
int main()
{
char position;
while(cin>>position)
{
if(position=='#') break;
vector<vector<cards>> handsin(4);
int weight;
switch(position) {
case 'S': {
weight = 3;
break;
}
case 'W': {
weight = 2;
break;
}
case 'N': {
weight = 1;
break;
}
case 'E': {
weight = 0;
break;
}
default : {
weight=-1;
break;
}
}
string str1;
string str2;
cin>>str1;
cin>>str2;
//发牌
for(int i=0,j=1;i<str1.size()&&j<str1.size();i=i+2,j=j+2)
{
int tmp=((i%8)/2);
cards newcard(str1[i],str1[j]);
handsin[tmp].push_back(newcard);
}
for(int i=0,j=1;i<str2.size()&&j<str2.size();i=i+2,j=j+2)
{
int tmp=(((i%8)/2)+2)%4;
cards newcard(str2[i],str2[j]);
handsin[tmp].push_back(newcard);
}
//排序
for(int i=0;i<4;i++)
{
int ch=(i+weight)%4;
Vsort(i,handsin[ch]);
}
cout<<endl;
}
return 0;
}