1. 程式人生 > >CCF 2018真題--持續更新ing

CCF 2018真題--持續更新ing

1 跳一跳

描述

近來,跳一跳這款小遊戲風靡全國,受到不少玩家的喜愛。
  簡化後的跳一跳規則如下:玩家每次從當前方塊跳到下一個方塊,如果沒有跳到下一個方塊上則遊戲結束。
  如果跳到了方塊上,但沒有跳到方塊的中心則獲得1分;跳到方塊中心時,若上一次的得分為1分或這是本局遊戲的第一次跳躍則此次得分為2分,否則此次得分比上一次得分多兩分(即連續跳到方塊中心時,總得分將+2,+4,+6,+8…)。
  現在給出一個人跳一跳的全過程,請你求出他本局遊戲的得分(按照題目描述的規則)。

分析

模擬場景,還是很簡單那種。一個sum記錄總分,一個last記錄上一層得分,1的時候直接sum++;2的時候根據last來加分並修改last的值,0的時候輸出並return

參考程式碼

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int n,sum=0,last=1;
    while (cin>>n)
    {
        if (n == 1){sum++;last =1;}
        else if(n==2)
        {
            if (last == 1){sum += 2;last = 2;}
            else {
                sum += (last + 2
); last += 2; } } else{ cout<<sum<<"\n"; return 0; } } }

2 碰撞的小球

描述

數軸上有一條長度為L(L為偶數)的線段,左端點在原點,右端點在座標L處。有n個不計體積的小球線上段上,開始時所有的小球都處在偶數座標上,速度方向向右,速度大小為1單位長度每秒。
  當小球到達線段的端點(左端點或右端點)的時候,會立即向相反的方向移動,速度大小仍然為原來大小。
  當兩個小球撞到一起的時候,兩個小球會分別向與自己原來移動的方向相反的方向,以原來的速度大小繼續移動。
  現在,告訴你線段的長度L,小球數量n,以及n個小球的初始位置,請你計算t秒之後,各個小球的位置。
  因為所有小球的初始位置都為偶數,而且線段的長度為偶數,可以證明,不會有三個小球同時相撞,小球到達線段端點以及小球之間的碰撞時刻均為整數。
  同時也可以證明兩個小球發生碰撞的位置一定是整數(但不一定是偶數)。

分析

也是模擬題,用了location陣列記錄每個小球的位置;v陣列記錄每個小球的速度;LL二維陣列(vector)記錄每個整數位置的小球的編號。在時間t下迴圈,每次遍歷一遍所有小球,根據v[i]修改其位置;遍歷完後遍歷位置,所有一個位置處小球數大於1的(只會有兩個),將這兩個編號小球的速度去相反數。看起來有點囉嗦

程式碼

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
const int maxx = 200;
const int Lmax = 1005;
int locations[maxx];
vector<vector<int> >LL;
int v[maxx];
int main()
{
    int n, L, t;
    while (cin >> n >> L >> t)
    {
        LL.clear();
        LL.resize(L + 1);
        for (int i = 0; i < n; i++)
        {
            cin >> locations[i];
            v[i] = 1;
        }

        while (t>0)
        {
            LL.clear();
            LL.resize(L + 1);
            for (int i = 0; i < n; i++)
            {
            if (locations[i] == L) {
            v[i] = -v[i];
            }

            locations[i] += v[i];
            LL[locations[i]].push_back(i);
            }
            for(int i =0;i<LL.size();i++)
                if (LL[i].size() > 1)
                {
                    v[LL[i][0]] = -v[LL[i][0]];
                    v[LL[i][1]] = -v[LL[i][1]];
                }
        t--;
        }
        for (int i = 0; i < n; i++)
            printf("%d ", locations[i]);
    }
    return 0;
}

不知道為什麼,在vs2017上這個報vector下標越界,但是我提交之後就過了。。過了

上面那個方法有點囉嗦,習慣了直接無視O(n^2)級別的演算法,沒想到也能過。就是遍歷查詢此刻有沒有位置相同的,然後修改兩者的方向就好了!O(n^2)!過了!

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxx = 200;
const int Lmax = 1005;
int locations[maxx];
int v[maxx];
int main()
{
    int n, L, t;
    while (cin >> n >> L >> t)
    {

        for (int i = 0; i < n; i++)
        {
            cin >> locations[i];
            v[i] = 1;
        }

        while (t>0)
        {
            //if (locations[0] == 0 && v[0] < 0)v[0] = -v[0];
            //if (locations[0] == L)v[0] = -v[0];
            //locations[0] = locations[0] + v[0];
            for (int i = 0; i < n; i++)
            {
                if (locations[i] == L || (locations[i] == 0&&v[i]<0))v[i] = -v[i];
                locations[i] = locations[i] + v[i];
                for(int j =0;j<n;j++)
                if (locations[i] == locations[j])
                {
                    v[i] = -v[i];
                    v[j] = -v[j];
                }
            }
        t--;
        }
        for (int i = 0; i < n; i++)
            printf("%d ", locations[i]);
    }
    return 0;
}

3 URL對映

描述

問題描述
  URL 對映是諸如 Django、Ruby on Rails 等網頁框架 (web frameworks) 的一個重要元件。對於從瀏覽器發來的 HTTP 請求,URL 對映模組會解析請求中的 URL 地址,並將其分派給相應的處理程式碼。現在,請你來實現一個簡單的 URL 對映功能。
  本題中 URL 對映功能的配置由若干條 URL 對映規則組成。當一個請求到達時,URL 對映功能會將請求中的 URL 地址按照配置的先後順序逐一與這些規則進行匹配。當遇到第一條完全匹配的規則時,匹配成功,得到匹配的規則以及匹配的引數。若不能匹配任何一條規則,則匹配失敗。
  本題輸入的 URL 地址是以斜槓 / 作為分隔符的路徑,保證以斜槓開頭。其他合法字元還包括大小寫英文字母、阿拉伯數字、減號 -、下劃線 _ 和小數點 .。例如,/person/123/ 是一個合法的 URL 地址,而 /person/123? 則不合法(存在不合法的字元問號 ?)。另外,英文字母區分大小寫,因此 /case/ 和 /CAse/ 是不同的 URL 地址。
  對於 URL 對映規則,同樣是以斜槓開始。除了可以是正常的 URL 地址外,還可以包含引數,有以下 3 種:
  字串 :用於匹配一段字串,注意字串裡不能包含斜槓。例如,abcde0123。
  整數 :用於匹配一個不帶符號的整數,全部由阿拉伯數字組成。例如,01234。
  路徑 :用於匹配一段字串,字串可以包含斜槓。例如,abcd/0123/。
  以上 3 種引數都必須匹配非空的字串。簡便起見,題目規定規則中 和 前面一定是斜槓,後面要麼是斜槓,要麼是規則的結束(也就是該引數是規則的最後一部分)。而 的前面一定是斜槓,後面一定是規則的結束。無論是 URL 地址還是規則,都不會出現連續的斜槓。
輸入格式
  輸入第一行是兩個正整數 n 和 m,分別表示 URL 對映的規則條數和待處理的 URL 地址個數,中間用一個空格字元分隔。
  第 2 行至第 n+1 行按匹配的先後順序描述 URL 對映規則的配置資訊。第 i+1 行包含兩個字串 pi 和 ri,其中 pi 表示 URL 匹配的規則,ri 表示這條 URL 匹配的名字。兩個字串都非空,且不包含空格字元,兩者中間用一個空格字元分隔。
  第 n+2 行至第 n+m+1 行描述待處理的 URL 地址。第 n+1+i 行包含一個字串 qi,表示待處理的 URL 地址,字串中不包含空格字元。
輸出格式
  輸入共 m 行,第 i 行表示 qi 的匹配結果。如果匹配成功,設匹配了規則 pj ,則輸出對應的 rj。同時,如果規則中有引數,則在同一行內依次輸出匹配後的引數。注意整數引數輸出時要把前導零去掉。相鄰兩項之間用一個空格字元分隔。如果匹配失敗,則輸出 404。
樣例輸入
5 4
/articles/2003/ special_case_2003
/articles// year_archive
/articles/// month_archive
/articles//// article_detail
/static/ static_serve
/articles/2004/
/articles/1985/09/aloha/
/articles/hello/
/static/js/jquery.js
樣例輸出
year_archive 2004
article_detail 1985 9 aloha
404
static_serve js/jquery.js
樣例說明
  對於第 1 個地址 /articles/2004/,無法匹配第 1 條規則,可以匹配第 2 條規則,引數為 2004。
  對於第 2 個地址 /articles/1985/09/aloha/,只能匹配第 4 條規則,引數依次為 1985、9(已經去掉前導零)和 aloha。
  對於第 3 個地址 /articles/hello/,無法匹配任何一條規則。
  對於第 4 個地址 /static/js/jquery.js,可以匹配最後一條規則,引數為 js/jquery.js。
資料規模和約定
  1 ≤ n ≤ 100,1 ≤ m ≤ 100。
  所有輸入行的長度不超過 100 個字元(不包含換行符)。
  保證輸入的規則都是合法的。

分析

這道題卡了很久..
算是一道大模擬的題,看上去不是很難,但是沒那麼容易過,最後的AC程式碼參考了 https://blog.csdn.net/nameofcsdn/article/details/79945925
m條URL每一個都要在n條規則中尋找一遍有沒有匹配的,還是把一條url與一條規則是否匹配單拿出來做函式的好
這位博主的程式碼用一個bool引數來確定這次是單純判斷是否符合還是輸出匹配的引數,反正我沒想到
判斷的時候用while迴圈比用for迴圈靈活許多,相等就continue;出現不等的情況,如果規則處不是’<’那肯定是不匹配了,return FALSE;
如果是’<’的話,就分三種情況:‘i’判斷數字,如果一直是數字就可以一直輸出,開始時判斷是否為0即可,如果不滿足這條規則就return false了,如果這個int匹配上了,就可以continue進行下一步了;
‘s’判斷str,輸出直到出現’/’為止;’p’判斷path,輸出直到最後。
最後如果沒有出現這些個引數的話,如果兩個一直匹配,那最後各自到達自己的長度時,就是完全匹配了

靈活使用continue return,讓程式碼變得很簡潔

程式碼

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<cctype>
using namespace std;
string rules[101],names[101], qs[101];
bool ismatch(string q, string rule,   bool flag)
{
    int qlen = q.length(), rlen = rule.length();
    int qi = 0, ri = 0;
    while (qi<qlen && ri<rlen)
    {
        if (q[qi] == rule[ri])
        {
            qi++; ri++; continue;
        }
        if (rule[ri++] != '<')return false;
        if (flag)cout << " ";
        if (rule[ri] == 'i') {
            bool flag2 = false;
            while (qi < qlen && q[qi] >= '0' && q[qi] <= '9')
            {
                if (q[qi] > '0')flag2 = true;
                if (flag && flag2)cout << q[qi];
                qi++;
            }
            if (flag2 == false)return false;
            ri += 4;
            continue;
        }
        else if (rule[ri] == 's')
        {
            bool flag2 = false;
            while (qi<qlen && q[qi]!='/' )
            {
                flag2 = true;
                if (flag2 && flag)cout << q[qi];
                qi++;
            }
            if (flag2 == false)return false;
            ri += 4;
            continue;
        }
        else if (rule[ri] == 'p')
        {
            while (qi<qlen)
            {
                if (flag)cout << q[qi];
                qi++;
            }
            return true;
        }
    }
    return (qi == qlen && ri == rlen);
}
int main()
{
    int n, m;
    while (cin>>n>>m)
    {
        for (int i = 0; i < n; i++)
        {
            cin >> rules[i]>>names[i];
        }
        string q;
        for (int i = 0; i < m; i++) {
            cin >> q;
            bool fl = false;
            for(int j=0;j<n;j++)
                if (ismatch(q, rules[j], false))
                {
                    fl = true;
                    cout << names[j] ;
                    ismatch(q, rules[j], true);
                    cout << "\n";
                    break;
                }
            if (fl == false)cout << "404\n";
        }



    }
}