CCF-2019-12三題

第一題:報數(shù)

【題目】:
甲乙丙丁決定玩一個報數(shù)的游戲來打發(fā)時間。游戲規(guī)則為四個人從1開始輪流進行報數(shù),但如果需要報出的數(shù)是7的倍數(shù)或含有數(shù)字7則直接跳過。
此外大家約定,在總共報出了n個數(shù)后(不計入被跳過的數(shù))游戲結束?,F(xiàn)在需要你來幫忙統(tǒng)計,游戲過程中每個人各自跳過了幾次。
【輸入】:
從標準輸入讀入數(shù)據(jù)。
輸入僅一行,包含一個正整數(shù)n,表示報出了多少個數(shù)后游戲結束。
【輸出】:
輸出到標準輸出。
輸出共四行,每行一個整數(shù),依次表示甲乙丙丁四人在游戲過程中跳過的次數(shù)。

思路:水題沒什么好說的,代碼如下

#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;
    }
}

第二題: 回收站選址

【題目】:
開學了,可是校園里堆積了不少垃圾雜物。
熱心的同學們紛紛自發(fā)前來清理,為學校注入正能量~
通過無人機航拍我們已經知曉了n處尚待清理的垃圾位置,其中第i(1<=i<=n)處的坐標為(x,y),保證所有的坐標均為整數(shù)。
我們希望在垃圾集中的地方建立些回收站。具體來說,對于一個位置(x, y)是否適合建立回收站,我們主要考慮以下幾點:
(x, y)必須是整數(shù)坐標,且該處存在垃圾:上下左右四個鄰居位置,即(x, y+1),(x, y-1),(x+1, y)和(x-1, y)處,必須全部存在垃圾:進一步地,我們會對滿足上述兩個條件的選址進行評分,分數(shù)為不大于4的自然數(shù),表示在(x±1,y±1)四個對角位置中有幾處存在垃圾。
現(xiàn)在,請你統(tǒng)計一下每種得分的選址個數(shù)。
【輸入】:
從標準輸入讀入數(shù)據(jù)。輸入總共有n+1行。
第1行包含一個正整數(shù)n,表示已查明的垃圾點個數(shù)。
第1+i行(1<=i<=n)包含由一個空格分隔的兩個整數(shù)xi和yi,表示第i處垃圾的坐標。
保證輸入的n個坐標互不相同。
【輸出】:
輸出到標準輸出。
輸出共五行,每行一個整數(shù),依次表示得分為0、1、2、3和4的回收站選址個數(shù)。

思路:
1.一般做題要么是用空間換時間要么是時間換空間,如果本體使用二維數(shù)組模擬坐標,測試用例是有用10000以上的坐標作為測試數(shù)據(jù)的,如果使用二維數(shù)組模擬坐標就說明最起碼得有index[10000][10000],這顯然不現(xiàn)實。
2.所以只能用時間換空間,大力出奇跡就完事了。直接用兩重循環(huán),依次比較一個點上下左右的坐標值在數(shù)組中有無對應,如果有再判斷對角線上的。時間復雜度為: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;
    }
}

第三題:化學方程式(沒做出)

【題目】:
化學方程式,也稱為化學反應方程式,是用化學式表示化學反應的式子。給出一組化學方程式,請你編寫程序判斷每個方程式是否配平(也就是方程式中等號左右兩邊的元素種類和對應的原子個數(shù)是否相同)。
本題給出的化學方程式由大小寫字母、數(shù)字和符號(包括等號=、加號+、左圓括號和右圓括號)組成,不會出現(xiàn)其他字符(包括空白字符,如空格、制表符等),化學方程式的格式與化學課本中的形式基本相同(化學式中表示元素原子個數(shù)的下標用正常文本,如H2O寫成H2O),用自然語言描述如下:

化學方程式由左右兩個表達式組成,中間用一個等號三連接,如2H2+O2=2H2O;
表達式由若干部分組成,每部分由系數(shù)和化學式構成,部分之間用加號+連接,如2H2+O2、2H2O;
系數(shù)是整數(shù)或空串,如為空串表示系數(shù)為1;
整數(shù)由一個或多個數(shù)字構成;
化學式由若干部分組成,每部分由項和系數(shù)構成,部分之間直接連接,如H2O、CO2、Ca(OH)2、Ba3(PO4)2;
項是元素或用左右圓括號括起來的化學式,如H、Ca、(OH)、(P04);
元素可以是一個大寫字母,也可以是一個大寫字母跟著一個小寫字母,如H、O、Ca。
【輸入】:
從標準輸入讀入數(shù)據(jù)。
輸入的第一行包含一個正整數(shù)n,表示輸入的化學方程式個數(shù)。
接下來n行,每行是一個符合定義的化學方程式。
【輸出】:
輸出到標準輸出。
輸出共n行,每行是一個大寫字母Y或N,回答輸入中相應的化學方程式是否配平。

思路:
1、一個元素必然由一個大寫字母開頭如C,Cl,所以將大寫字母開頭的視為一個元素,如果開頭的是數(shù)字,那么后面全體元素個數(shù)都要乘以這個數(shù)字,如果數(shù)字在元素后面出現(xiàn),那么這個數(shù)字的前一個元素就要乘以這個數(shù)字。
做不出來的地方:括號嵌套。有些案例嵌套非常多的括號,如果要解決這個問題要加入很多判斷,我又想不到特別精簡的做法。最近忙著學習安卓開發(fā),無瑕再畫大量時間去剛一道碼量巨多的題。

#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]))//如果某個開頭是數(shù)字,就要確認他的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++)//回到第一個字符出現(xiàn)的位置
                    {
                        hash[equation_part[i][k]] += 1 * base*end_base;
                    }
                    //更新下一個字符起始位置,循環(huán)結束會++
                    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++)//回到第一個字符出現(xiàn)的位置
                    {
                        hash[equation_part[i][k]] += 1 * base*end_base;
                    }
                    //更新下一個字符起始位置,循環(huán)結束會++,所以在此減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++)//回到第一個字符出現(xiàn)的位置
                    {
                        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++)//回到第一個字符出現(xiàn)的位置
                    {
                        hash[equation_part[i][k]] += 1 * base*end_base;
                    }
                    //更新下一個字符起始位置,循環(huán)結束會++,所以在此減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;
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容