《程序设计思维与实践》 week2—实验题

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
是同一种,本质上就是一条链,编号其实是没有关系的,可以在纸上画画就懂了

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

解题思路

五种烷烃基HDMG的特点

n - hexane —— 一个化学键的原子 x 2;两个化学键的原子 x 4;
2,2 - dimethylbutane —— 一个化学键的原子 x 4;两个化学键的原子 x 1;四个化学键的原子 x 1;
2,3 - dimethylbutane —— 一个化学键的原子 x 4;三个化学键的原子 x 2;
2 - methylpentane3 - methylpentane —— 一个化学键的原子 x 3;两个化学键的原子 x 2;三个化学键的原子 x 1;
判断的重点就是在与2 - methylpentane 和 3 - methylpentane
对于2 - methylpentane:有三个化学键的那个原子,与其相连的原子中有一个原子其化学键数为1;
对于3 - methylpentane:有三个化学键的那个原子,与其相连的原子中有两个原子其化学键数为1;

d[ ] 和 s[ ] 和 x[ ] [ ]

d[ ] 用于储存从1~5号原子的化学键的数目;
s[ ] 用于储存每种化学键的数目;
x[ ] [ ] 用于储存原子之间的连接关系,即是一个化学键两边连接的原子编号;

判断方法

依据五种烷烃基HDMG的特点进行判断,主要就是涉及到s[ ]中目标化学键的数目;
对于2 - methylpentane 和 3 - methylpentane 则是通过访问x[ ] [ ],记录化学键数目为3的相邻原子的化学键数,用count去记录相邻原子中化学键数为1的数目;count = 1 即是3 - methylpentane;count = 2 即是2 - methylpentane;

解题代码

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

int a, b;
int x[5][2];

int main()
{
    int T;
    while (cin>>T) {
        for (int l = 0; l < T; l++) {
            int d[] = {0, 0, 0, 0, 0, 0};
            int s[] = {0, 0, 0, 0};
            
            for (int m = 0; m < 5; m++){
                cin>>a>>b;
                d[a-1]++; d[b-1]++;
                x[m][0] = a; x[m][1] = b;
            }
            
            for (int c = 0; c < 6; c++) s[d[c] - 1]++;
            
            if (s[0] == 2 && s[1] == 4) {
                cout<<"n-hexane"<<endl;
                continue;
            }
            if (s[0] == 4 && s[1] == 1 && s[3] == 1) {
                cout<<"2,2-dimethylbutane"<<endl;
                continue;
            }
            if (s[0] == 4 && s[2] == 2) {
                cout<<"2,3-dimethylbutane"<<endl;
                continue;
            }
            if (s[0] == 3 && s[1] == 2 && s[2] == 1) {
                int z = 0;
                int count = 0;
                for (int w = 0; w < 6; w++) {
                    if (d[w] == 3) {
                        z = w;
                        break;
                    }
                }
                for (int e = 0; e < 5; e++) {
                    for (int r = 0; r < 2; r++) {
                        if (x[e][r] == z + 1 && r == 0 && d[x[e][r+1] - 1] == 1) count++;
                        if (x[e][r] == z + 1 && r == 1 && d[x[e][r-1] - 1] == 1) count++;
                    }
                }
                if (count == 1) cout<<"3-methylpentane"<<endl;
                if (count == 2) cout<<"2-methylpentane"<<endl;
                continue;
            }
        }
        
    }
}

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

解题思路

输入信息的处理

一行的输入包括姓名以及各个题目的成绩,我将一行切成两部分,姓名是一部分,然后分数为一部分,由于题目的数量是已知的,所以可以用一个for循环对每一题的情况进行分析;

成绩的处理

1、负数 直接跳过不进行处理;
2、非负数(不带括号) 将每一位存入到数组中,同时记录其位数,获得该题时间分数;
3、非负数(带括号) 首先将“ ( ”之前的所有数存入数组中进行处理并记录,然后清空数组,接着计算括号里面的数据,两者相加,获得该题时间分数;

输出格式
cout<<setw(n)<<left/right<<element;
// n 确定输出的元素长度;left/right 确定输出的格式是左对齐或者右对齐;

解题代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <iomanip>
#include <vector>
#include <cmath>

using namespace std;

int n, m;
vector<int> score; //成绩的每一位
vector<string> s;  //每一门成绩

struct s_i{
    string name;
    int AN = 0;
    int TS = 0;
};

bool PX(s_i A, s_i B){
    if (A.AN == B.AN) {
        if (A.TS == B.TS) {
            return A.name < B.name;
        }
        return A.TS < B.TS;
    }
    return A.AN > B.AN;
}

int main()
{
    cin>>n>>m;
    string i1;
    vector<s_i> Rank;
    while (cin>>i1) {
        s_i A;
        A.name = i1;
        string i2;
        for (int l = 0; l < n; l++) {
            cin>>i2;
            s.push_back(i2);
        }
        for (int l = 0; l < n; l++) {
            int s1 = 0, s2 = 0;
            string d = s[l];
            string::iterator w = d.begin();
            while (w != d.end()) {
                if (*w == '-') break;
                if (*w >= '0' && *w <= '9') score.push_back(*w - '0');
                if (*w == '(') {
                    long int t = score.size();
                    for (long int f = 0; f < score.size(); f++) {
                        s1 = s1 + pow(10, t - 1) * score[f];
                        t--;
                    }
                    score.clear();
                }
                if (*w == ')') {
                    long int t = score.size();
                    for (long int f = 0; f < score.size(); f++) {
                        s2 = s2 + pow(10, t - 1) * m * score[f];
                        t--;
                    }
                    score.clear();
                }
                w++;
            }
            if (score.size() != 0) {
                long int t = score.size();
                for (long int f = 0; f < score.size(); f++) {
                    s1 = s1 + pow(10, t - 1) * score[f];
                    t--;
                }
                score.clear();
            }
            A.AN++;
            int ss = s1 + s2;
            if (ss == 0) A.AN--;
            A.TS = A.TS + ss;
        }
        Rank.push_back(A);
        s.clear();
    }

    sort(Rank.begin(), Rank.end(), PX);
    for (long int v = 0; v < Rank.size(); v++) {
        cout<<setw(10)<<left<<Rank[v].name<<" ";
        cout<<setw(2)<<right<<Rank[v].AN<<" ";
        cout<<setw(4)<<right<<Rank[v].TS;
        cout<<endl;
    }
    Rank.clear();
}

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

解题思路

确定位置、花色、牌值的等级顺序

字符串数组 wanjia[ ]、huase[ ] 和 paizhi[ ] 分别按规定的大小顺序储存玩家位置、花色、牌值,通过自定义函数RankW,RankH, RankZ根据花色、牌值的值返回其大小顺序;

处理输入信息

第一个输入的一定是开始发牌的位置信息,单独进行处理,用一个全局变量b进行存储;
后面输入的信息,则根据其长度进行不同的处理。如果长度为1,那么可能是开始下一轮发牌操作,也可能就是结束牌局,所以这之前就需要对已经获取到的每个人的所有牌按照规定的规则进行输出;如果长度大于一,则从头开始读取,每次读取两个字节,根据b去得到下一个获得牌的玩家位置信息,每次读取两个,然后进入下一个两个,同时b++;

解题代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <iomanip>
#include <vector>
#include <cmath>
using namespace std;

string wanjia[] = {"N", "E", "S", "W"};
char huase[] = {'C', 'D', 'S', 'H'};
char paizhi[] = {'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};

int RankW(string w){
    for (int n = 0; n < 4; n++) {
        if (w == wanjia[n]) {return n;}
    }
    return 5;
}
int RankH(char h){
    for (int n = 0; n < 4; n++) {
        if (h == huase[n]) {return n;}
    }
    return 5;
}
int RankZ(char z){
    for (int n = 0; n < 13; n++) {
        if (z == paizhi[n]) {return n;}
    }
    return 14;
}

struct pai {
    char HS;
    char PZ;
    
    pai() {}
    pai(char a, char b) {HS = a; PZ = b;}
};

bool PX (pai a, pai b) {
    if (RankH(a.HS) != RankH(b.HS))
        return RankH(a.HS) < RankH(b.HS);
    else
        return RankZ(a.PZ) < RankZ(b.PZ);
}

vector<pai> N;
vector<pai> E;
vector<pai> S;
vector<pai> W;

void input(int a, pai p) {
    if (a == 0) {N.push_back(p); return;}
    if (a == 1) {E.push_back(p); return;}
    if (a == 2) {S.push_back(p); return;}
    if (a == 3) {W.push_back(p); return;}
}

void output(vector<pai> s) {
    cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
    cout<<"|";
    for (int n = 0; n < 13; n++) {cout<<s[n].PZ<<" "<<s[n].PZ<<"|";}
    cout<<endl<<"|";
    for (int n = 0; n < 13; n++) {cout<<" "<<s[n].HS<<" "<<"|";}
    cout<<endl<<"|";
    for (int n = 0; n < 13; n++) {cout<<s[n].PZ<<" "<<s[n].PZ<<"|";}
    cout<<endl;
    cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
}

string Poker;
int b;
pai p;

int main()
{
    cin>>Poker;
    b = (RankW(Poker) + 1) % 4;
    while (cin>>Poker) {
        if (Poker.size() == 1) {
            sort(S.begin(), S.begin() + 13, PX);
            sort(W.begin(), W.begin() + 13, PX);
            sort(N.begin(), N.begin() + 13, PX);
            sort(E.begin(), E.begin() + 13, PX);
            cout<<"South player:"<<endl;
            output(S); S.clear();
            cout<<"West player:"<<endl;
            output(W); W.clear();
            cout<<"North player:"<<endl;
            output(N); N.clear();
            cout<<"East player:"<<endl;
            output(E); E.clear();
            cout<<endl;
            
            if (Poker == "#") return 0;
            else {
                b = (RankW(Poker) + 1) % 4;
                continue;
            }
        }
        for (int n = 0; n < 51; n = n + 2) {
            p.HS = Poker[n];
            p.PZ = Poker[n+1];
            input(b, p);
            b = (b + 1) % 4;
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值