CCF-2019-12三题

第一题:报数

【题目】:
甲乙丙丁决定玩一个报数的游戏来打发时间。游戏规则为四个人从1开始轮流进行报数,但如果需要报出的数是7的倍数或含有数字7则直接跳过。
此外大家约定,在总共报出了n个数后(不计入被跳过的数)游戏结束。现在需要你来帮忙统计,游戏过程中每个人各自跳过了几次。
【输入】:
从标准输入读入数据。
输入仅一行,包含一个正整数n,表示报出了多少个数后游戏结束。
【输出】:
输出到标准输出。
输出共四行,每行一个整数,依次表示甲乙丙丁四人在游戏过程中跳过的次数。

思路:水题没什么好说的,代码如下

#include<iostream>
using namespace std;
int main()
{
    int n;
    int gamer[10];
    int number;
    int count;
    while (cin >> n)
    {
        count=gamer[1] = gamer[2] = gamer[3] = gamer[0]=0;
        for (int i = 1; count!=n; i++)
        {
            if (i % 7 == 0)
            {
                gamer[i % 4]++;
                continue;
            }
            else 
            {
                number = i;
                while (number)
                {
                    if (number % 10 == 7)
                    {
                        gamer[i % 4]++;
                        count--;
                        break;
                    }
                    else number = number / 10;
                }
            }
            count++;
        }
                //4取余是0,故丁的位置在gamer[0]而不是gamer[4]
        cout << gamer[1] << endl << gamer[2] << endl << gamer[3] << endl << gamer[0] << endl;
    }
}

第二题: 回收站选址

【题目】:
开学了,可是校园里堆积了不少垃圾杂物。
热心的同学们纷纷自发前来清理,为学校注入正能量~
通过无人机航拍我们已经知晓了n处尚待清理的垃圾位置,其中第i(1<=i<=n)处的坐标为(x,y),保证所有的坐标均为整数。
我们希望在垃圾集中的地方建立些回收站。具体来说,对于一个位置(x, y)是否适合建立回收站,我们主要考虑以下几点:
(x, y)必须是整数坐标,且该处存在垃圾:上下左右四个邻居位置,即(x, y+1),(x, y-1),(x+1, y)和(x-1, y)处,必须全部存在垃圾:进一步地,我们会对满足上述两个条件的选址进行评分,分数为不大于4的自然数,表示在(x±1,y±1)四个对角位置中有几处存在垃圾。
现在,请你统计一下每种得分的选址个数。
【输入】:
从标准输入读入数据。输入总共有n+1行。
第1行包含一个正整数n,表示已查明的垃圾点个数。
第1+i行(1<=i<=n)包含由一个空格分隔的两个整数xi和yi,表示第i处垃圾的坐标。
保证输入的n个坐标互不相同。
【输出】:
输出到标准输出。
输出共五行,每行一个整数,依次表示得分为0、1、2、3和4的回收站选址个数。

思路:
1.一般做题要么是用空间换时间要么是时间换空间,如果本体使用二维数组模拟坐标,测试用例是有用10000以上的坐标作为测试数据的,如果使用二维数组模拟坐标就说明最起码得有index[10000][10000],这显然不现实。
2.所以只能用时间换空间,大力出奇迹就完事了。直接用两重循环,依次比较一个点上下左右的坐标值在数组中有无对应,如果有再判断对角线上的。时间复杂度为:o(n^2)。

代码如下:

#pragma warning(disable:4996)
#include<iostream>
using namespace std;
int main()
{
    int n;
    int dp;
    int input[500];
    int member[20];
    int i,j;
    int flag;
    while (cin >> n)
    {
        memset(member, 0, sizeof(member));
        for (i = 0; i < 2 * n; i = i + 2)
            cin >> input[i] >> input[i + 1];

        for (i = 0, flag = 0, dp = 0; i < 2 * n; i = i + 2,flag=0,dp=0)
        {   
            for (j = 0;j < 2 * n; j = j + 2)
            {
                if ((input[i] + 1 == input[j] && input[i + 1] == input[j + 1]) ||
                    (input[i] == input[j] && input[i + 1] + 1 == input[j + 1]) ||
                    (input[i] - 1 == input[j] && input[i + 1] == input[j + 1]) ||
                    (input[i] == input[j] && input[i + 1] - 1 == input[j + 1])
                    )flag++;
                
            }
            if (flag == 4)
            {
                for (j = 0; j < 2 * n; j = j + 2)
                {
                    if ((input[i] + 1 == input[j] && input[i + 1] + 1 == input[j + 1]) ||
                        (input[i] + 1 == input[j] && input[i + 1] - 1 == input[j + 1]) ||
                        (input[i] - 1 == input[j] && input[i + 1] + 1 == input[j + 1]) ||
                        (input[i] - 1 == input[j] && input[i + 1] - 1 == input[j + 1])
                        )dp++;
                }
                member[dp]++;
            }
            
            
        }
        cout << member[0] << endl << member[1] << endl << member[2] << endl << member[3] << endl << member[4] << endl;
    }
}

第三题:化学方程式(没做出)

【题目】:
化学方程式,也称为化学反应方程式,是用化学式表示化学反应的式子。给出一组化学方程式,请你编写程序判断每个方程式是否配平(也就是方程式中等号左右两边的元素种类和对应的原子个数是否相同)。
本题给出的化学方程式由大小写字母、数字和符号(包括等号=、加号+、左圆括号和右圆括号)组成,不会出现其他字符(包括空白字符,如空格、制表符等),化学方程式的格式与化学课本中的形式基本相同(化学式中表示元素原子个数的下标用正常文本,如H2O写成H2O),用自然语言描述如下:

化学方程式由左右两个表达式组成,中间用一个等号三连接,如2H2+O2=2H2O;
表达式由若干部分组成,每部分由系数和化学式构成,部分之间用加号+连接,如2H2+O2、2H2O;
系数是整数或空串,如为空串表示系数为1;
整数由一个或多个数字构成;
化学式由若干部分组成,每部分由项和系数构成,部分之间直接连接,如H2O、CO2、Ca(OH)2、Ba3(PO4)2;
项是元素或用左右圆括号括起来的化学式,如H、Ca、(OH)、(P04);
元素可以是一个大写字母,也可以是一个大写字母跟着一个小写字母,如H、O、Ca。
【输入】:
从标准输入读入数据。
输入的第一行包含一个正整数n,表示输入的化学方程式个数。
接下来n行,每行是一个符合定义的化学方程式。
【输出】:
输出到标准输出。
输出共n行,每行是一个大写字母Y或N,回答输入中相应的化学方程式是否配平。

思路:
1、一个元素必然由一个大写字母开头如C,Cl,所以将大写字母开头的视为一个元素,如果开头的是数字,那么后面全体元素个数都要乘以这个数字,如果数字在元素后面出现,那么这个数字的前一个元素就要乘以这个数字。
做不出来的地方:括号嵌套。有些案例嵌套非常多的括号,如果要解决这个问题要加入很多判断,我又想不到特别精简的做法。最近忙着学习安卓开发,无瑕再画大量时间去刚一道码量巨多的题。

#pragma warning(disable:4996)
#include<iostream>
#include<sstream>
#include <string>
#include <vector>
#include<algorithm>
#include<map>
#include<ctype.h>
#include <math.h> 
using namespace std;

bool judge(map<char, int> &left, map<char, int> &right) { //判断两个map是否相同 
    if (left.size() != right.size()) return false;
    for (map<char, int>::iterator it = left.begin(); it != left.end(); ++it) {
        if (right[it->first] != it->second) return false;
    }
    return true;
}

int get_string_int(string s, int pos)
{
    int number;
    int j;
    stringstream stream;
    string num;
    for (j = pos + 1;  j < s.length(); j++)
        if (!isdigit(s[j])) 
            break;
    num = s.substr(pos, j);//substr不包括j
    stream<<num;
    stream >> number;
    return number;
}

map<char, int> count_alphabet(string equation_part[50])
{
    int i,j,k,now_index,base,end_base;
    map<char, int> hash;
    for (i = 0; i < equation_part->length(); i++)
    {
        
        if (isdigit(equation_part[i][0]))//如果某个开头是数字,就要确认他的base
        {

            base = get_string_int(equation_part[i], 0);
            
            for (j  = log10(base) + 1, now_index= log10(base); j < equation_part[i].length(); j++)//计算字符    
            {

                if (isdigit(equation_part[i][j]))
                {
                    //cout << "left_equation_part[i][j])=" << left_equation_part[i][j]<< endl;
                    end_base = get_string_int(equation_part[i], j);//这一行出异常
                    //cout << "base=" << base << "   " << "end_base=" << end_base << endl;
                    for (k = now_index; k < j; k++)//回到第一个字符出现的位置
                    {
                        hash[equation_part[i][k]] += 1 * base*end_base;
                    }
                    //更新下一个字符起始位置,循环结束会++
                    j = now_index = j + log10(end_base);
                }
                else if (j == equation_part[i].length()-1)
                {

                    end_base = 1;//这一行出异常
                    //cout << "base=" << base << "   " << "end_base=" << end_base << endl;
                    for (k = now_index+1; k <= j; k++)//回到第一个字符出现的位置
                    {
                        hash[equation_part[i][k]] += 1 * base*end_base;
                    }
                    //更新下一个字符起始位置,循环结束会++,所以在此减1
                    j = now_index = j + log10(end_base);
                    
                }
            }
        }
        else
        {
            base = 1;
            for (j = now_index = 0; j < equation_part[i].length(); j++)//计算字符   
            {
                if (isdigit(equation_part[i][j]))
                {
                    end_base = get_string_int(equation_part[i], j);//这一行出异常
                    for (k = now_index; k < j; k++)//回到第一个字符出现的位置
                    {
                        hash[equation_part[i][k]] += 1 * base*end_base;
                    }
                    j = now_index = j + log10(end_base);
                }
                else if (j == equation_part[i].length() - 1)
                {

                    end_base = 1;//这一行出异常
                    //cout << "base=" << base << "   " << "end_base=" << end_base << endl;
                    for (k = now_index + 1; k <= j; k++)//回到第一个字符出现的位置
                    {
                        hash[equation_part[i][k]] += 1 * base*end_base;
                    }
                    //更新下一个字符起始位置,循环结束会++,所以在此减1
                    j = now_index = j + log10(end_base);

                }
            }
        }
    }
    return hash;
}
int main()
{
    map<char, int> left_map;
    map<char, int> right_map;
    int n,m;
    int i, j, k;
    int base,end_base;
    int index,pos,now_index;
    string total_equation;
    string left_equation;
    string right_equation;
    string left_equation_part[50];
    string right_equation_part[50];

    cin >> n;
    while (n)
    {
        pos=m=index = 0;
        cin >> total_equation;
        left_equation = total_equation.substr(0, total_equation.find("="));
        right_equation = total_equation.substr(total_equation.find("=")+1,total_equation.length());
        //切割等号左边
        while (left_equation.find("+",pos)!=string::npos)
        {
            index = left_equation.find("+",pos);
            left_equation_part[m++] = left_equation.substr(pos,index);
            pos = index+1;
        }
        left_equation_part[m++] = left_equation.substr(pos, left_equation.length());
        //切割等号右边
        pos = m = index = 0;
        while (right_equation.find("+", pos) != string::npos)
        {
            index = right_equation.find("+", pos);
            right_equation_part[m++] = right_equation.substr(pos, index);
            pos = index + 1;
        }
        right_equation_part[m++] = right_equation.substr(pos, right_equation.length());

        cout << left_equation << endl<<"?"<< right_equation_part[0] <<endl;

        //下面开始处理左边的
        //cout << "下面开始处理左边的" << endl;
        left_map=count_alphabet(left_equation_part);
        
        //下面开始处理右边的
        //cout << "下面开始处理右边的" << endl;
        right_map=count_alphabet(right_equation_part);
        


        if (judge(left_map, right_map)) cout << "Y" << endl;
        else cout << "N" << endl;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351