zoukankan      html  css  js  c++  java
  • 程序设计思维与实践 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

    问题分析:

    从化学角度找规律,是比较容易的。有i个碳碳键的原子数目可以很好的统计出来,比如,3-methylpentane中,3个原子有1个碳碳键,2个原子有2个碳碳键,中间1个原子有1个碳碳键。考虑到这点性质和2-methylpentane一样,但是和剩下的三个都不一样,而且剩下的三个各不一样,所以接下来区分2-methylpentane和2-methylpentane。

    显然可以记录含3个碳碳键的碳原子及与其相邻的碳原子。对于2-methylpentane来说,与它相邻的碳原子,有2个含1个碳碳键,有1个含两个碳碳键。

     

    #include <iostream>
    using namespace std;
    
    int main()
    {
        int n;
        cin >> n;
        for (int i = 0; i < n; ++i)
        {
            int num_key[5];//有i个键的原子的数目
            for (int p = 0; p < 5; ++p)
                num_key[p] = 0;
            int atom_key[7];//第i的原子的键的数目,i=1,2,...,6
            for (int p = 0; p < 7; ++p)
                atom_key[p] = 0;
    
            int matrix[7][7];
            for (int p = 0; p < 7; ++p)
                for (int q = 0; q < 7; ++q)
                    matrix[p][q] = 0;
            int a, b;
            for (int j = 0; j < 5; ++j)
            {
                cin >> a >> b;
                matrix[a][b] = 1;
                matrix[b][a] = 1;
                atom_key[a]++;
                atom_key[b]++;
            }
    
            for (int r = 1; r <= 6; ++r)
            {
                if (atom_key[r] == 1)
                    num_key[1]++;
                else if (atom_key[r] == 2)
                    num_key[2]++;
                else if (atom_key[r] == 3)
                    num_key[3]++;
                else if (atom_key[r] == 4)
                    num_key[4]++;
            }
            
            if (num_key[1] == 2 && num_key[2] == 4)
                cout << "n-hexane" << endl;
            else if (num_key[1] == 3 && num_key[2] == 2 && num_key[3] == 1)
            {
                int atom_key3;
                for (int w = 1; w <= 6; ++w)
                    if (atom_key[w] == 3)
                        atom_key3 = w;
                int temp1 = 0;
                int temp2 = 0;
                for (int u = 1; u <= 6; ++u)
                {
                    if (matrix[atom_key3][u] == 1)
                    {
                        if (atom_key[u] == 1)
                            temp1++;
                        else if (atom_key[u] == 2)
                            temp2++;
                    }
                }
                if (temp1 == 2)
                    cout << "2-methylpentane" << endl;
                else
                    cout << "3-methylpentane" << endl;
            }
            else if (num_key[1] == 4 && num_key[2] == 0 && num_key[3] == 2)
                cout << "2,3-dimethylbutane" << endl;
            else if (num_key[1] == 4 && num_key[2] == 1 && num_key[4] == 1)
                cout << "2,2-dimethylbutane" << 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

    问题分析:

    着重做以下三件事:

    1,将参赛者的信息用结构体储存起来,包括姓名,ac数目,得分

    2,读入数据,判断读入的格式,计算或者直接将相关信息填入结构体中

    3,写排序规则,排序后输出

    具体来说,比较难的是读入数据。使用助教的方法,用scanf从键盘读入字符串,然后用sscanf读字符串到指定变量,是最方便的,容易区分得分和罚时。我用的方法很繁琐,是分析、判断string,从string中读有效的数据。这一点需要注意。

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <iomanip>
    
    using namespace std;
    
    struct node
    {
        string name;
        int ac = 0;
        int score = 0;
    };
    
    node stu[10005];
    bool cmp(const node& x, const node& y)
    {
        if (x.ac != y.ac)
            return x.ac > y.ac;
        else if (x.score != y.score)
            return x.score < y.score;
        else
            return x.name < y.name;
    }
    int main()
    {
        int n, m;
        cin >> n >> m;
        int t = 0;
        while (cin >> stu[t].name)
        {
            stu[t].ac = 0; stu[t].score = 0;
            for (int i = 0; i < n; i++)
            {
                string info;
                cin >> info;
                if (info[0] == '-')
                    continue;
                if (info[0] == '0')
                    continue;
                stu[t].ac++;
                int len = info.length();
                int p, s = 0;
    
                for (p = 0; p < len; p++)
                {
                    if (info[p] == '(') break;
                    s = s * 10 + info[p] - '0';
                }
                stu[t].score += s;
                s = 0;
                if (p < len)
                {
                    for (int k = p + 1; k < len - 1; k++)
                    {
                        s = s * 10 + info[k] - '0';
                    }
                }
                stu[t].score += s * m;
            }
            t++;
        }
        sort(stu, stu + t, cmp);       
        for (int i = 0; i < t; ++i)
        {
            cout << setiosflags(ios::left) << setw(10) << stu[i].name;
            printf_s(" %2d %4d
    ", stu[i].ac, stu[i].score);
        }
        return 0;
    }

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

     问题分析

    牌的顺序已经定下来了,只需要分发给四个玩家即可。使用简单的循环,用一个结构体数组代表一个玩家,每个结构体代表一张扑克,储存花色和大小,然后读入发牌顺序,从指定的玩家开始,顺时针依次发牌给玩家。

    值得注意的是,单独写两个函数,一个是吧花色转化为整数,例如,按照规则,A最大,所以定为14,然后T,J,Q,K一次是10,11,12,13,其余数字转化为相应的整数就可以了。这样有利于排序。另一个函数正好相反,把储存的数转化为代表花色的字符,方便输出。

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    struct poker
    {
        char type;
        int size;
    };
    
    poker player[4][13];//player[0] is in south, [1] in west, [2] in north, [3] in east
    
    int char2size(const char& c)
    {
        if (c >= '2' && c <= '9')
            return (c - '0');
        else if (c == 'A')
            return 14;
        else if (c == 'T')
            return 10;
        else if (c == 'J')
            return 11;
        else if (c == 'Q')
            return 12;
        else if (c == 'K')
            return 13;
        return -1;
    }
    
    char size2char(const int& c)
    {
        if (c >= 2 && c <= 9)
            return (c + '0');
        else if (c == 14)
            return 'A';
        else if (c == 10)
            return 'T';
        else if (c == 11)
            return 'J';
        else if (c == 12)
            return 'Q';
        else if (c == 13)
            return 'K';
        return 0;
    }
    
    bool comp(const poker& p1, const poker& p2)
    {
        int q1 = 0, q2 = 0;
        if (p1.type == 'C')
            q1 = 0;
        else if (p1.type == 'D')
            q1 = 1;
        else if (p1.type == 'S')
            q1 = 2;
        else if (p1.type == 'H')
            q1 = 3;
    
        if (p2.type == 'C')
            q2 = 0;
        else if (p2.type == 'D')
            q2 = 1;
        else if (p2.type == 'S')
            q2 = 2;
        else if (p2.type == 'H')
            q2 = 3;
    
        if (q1 != q2)
            return q1 < q2;
        else
            return p1.size < p2.size;
    }
    
    int main()
    {
        char n;
        while (cin >> n && n != '#')
        {
            int start = 0;
            if (n == 'S')
                start = 1;
            else if (n == 'W')
                start = 2;
            else if (n == 'N')
                start = 3;
            else if (n == 'E')
                start = 0;
            string order;
            int i = start;
            int p[4] = { 0,0,0,0 };
            for (int r = 0; r < 2; ++r)
            {
                cin >> order;
                int len = order.length();
                int point = 0;
                for (i; point < len; )
                {
                    player[i][p[i]].type = order[point++]; 
                    player[i][p[i]].size = char2size(order[point++]);
                    p[i]++;
                    i += 1;
                    i %= 4;
                }
            }
    
            for (int k = 0; k < 4; ++k)
            {
                sort(player[k], player[k] + 13, comp);
            }
            for (int k = 0; k < 4; ++k)
            {
                if (k == 0)
                    cout << "South player:" << endl;
                else if (k == 1)
                    cout << "West player:" << endl;
                else if (k == 2)
                    cout << "North player:" << endl;
                else if (k == 3)
                    cout << "East player:" << endl;
    
    
                for (i = 0; i < 13; ++i)
                    cout << '+' << '-' << '-' << '-';
                cout <<'+'<< endl;
    
                for (i = 0; i < 13; ++i)
                {
                    char c = size2char(player[k][i].size);
                    cout << '|' << c << ' ' << c;
                }
                cout <<'|'<< endl;
    
                for (i = 0; i < 13; ++i)
                    cout << '|' << ' ' << player[k][i].type << ' ';
                cout <<'|'<< endl;
    
                for (i = 0; i < 13; ++i)
                {
                    char c = size2char(player[k][i].size);
                    cout << '|' << c << ' ' << c;
                }
                cout << '|' << endl;
    
                for (i = 0; i < 13; ++i)
                    cout << '+' << '-' << '-' << '-';
                cout << '+' << endl;
            }
            cout << endl;
        }
        return 0;
    }

     

     

     

     

     

  • 相关阅读:
    ftell
    diff
    继承
    类的组合
    拷贝构造函数
    内存管理
    Hibernate学习-Hibernate查询语言HQL
    JAVA解析JSON数据
    Android异步加载
    Android数据存储-文件操作
  • 原文地址:https://www.cnblogs.com/master-cn/p/12411633.html
Copyright © 2011-2022 走看看