CSDN竞赛6期题解
CSDN編程競賽報名地址:https://edu.csdn.net/contest/detail/16
(請不要刪掉此地址)
總結
這次競賽題目比較簡單,沒多大必要寫題解。更多的還是給出自己的一些體會和建議吧。
很多同學已經對比賽規則和編程體驗給出了建議,比如復制粘貼自己在當前頁面寫的代碼也計算粘貼次數很不合理,遇見for循環或者名稱較長的變量不能復制只能手敲體驗不太好;題目給出了標準輸入的語句,但是給出的solution接口遠不如leetcode的接口友好,比如答案需要用long long表示,給出的模板函數返回值還是int,容易給人誤導。再比如調試需要完成等待幾秒才能再次調試或者提交,以及調試過程中的warning信息會參與結果的比對等等。我主要的建議還是在命題方面。
作為大規模的競賽,這次競賽的命題真的很不用心。競賽一般都是出的新題,而這次比賽直接從之前csdn的每日一題中隨機抽了幾題,而且難度也沒有控制好,題目過于簡單沒有區分度。而且題目的描述不夠詳細,用例不夠詳細。
我的建議是:找個有算法競賽背景命題人出新題,而不是隨便在題庫里抽題,才能保證公平性。命題完成需要另外的人進行審核,題目語義是否準確,用例是否充分,難度設置是否合理。都是需要review的地方,不是一兩句話概括題意,用例隨便出個簡單的,連基本輸入格式都沒有覆蓋到,每道題至少出三個用例,覆蓋不同的情況。下面結合具體題目來說下具體有哪些需要改進的地方吧。
題目列表
1.嚴查槍火
題目描述
X國最近開始嚴管槍火。 像是“ak”,“m4a1”,“skr”。都是明令禁止的。 現在小Q查獲了一批違禁物品其中部分是槍支。
小Q想知道自己需要按照私藏槍火來關押多少人。 (只有以上三種槍被視為違法)
分析
作為簡單的模擬題,如果給出了清晰的接口,是可以在兩分鐘內ac本題的,但是比賽時WA了幾次才通過這題。因為題目沒有對輸入格式清晰地描述出來,這也與一開始我選擇刪掉題目的輸入模板自己寫輸入有關,如果選擇自己寫輸入的同學,就會發現題目對輸入的描述有多么模糊了。
題目首先給定一個輸入n,接下來輸入n行字符串表示每個人攜帶的物品,問最后要關押多少人。題目唯一給的用例是一行一個字符串的情況,那么對于題意就有幾種理解了:
- 1.輸入n個字符串,判斷這n個字符串中包含違禁物品的有幾個。
- 2.輸入n行字符串,每行字符串是連續的,通過對每行字符串的子串是否包含違禁品來判斷是否應該關押。
- 3.輸入n行字符串,每行字符串由多個按空格隔開的字符串表示,表示每個人攜帶的若干件物品的名字,只要攜帶了違禁品就關押。
顯然,根據題意是無法判斷題目輸入到底是什么格式的,只能不斷的提交,一種情況一種情況的嘗試,直至通過本題。而最終題目后臺的輸入格式是第三種情況,我覺得要么題目描述清楚,每行表示每個人攜帶的若干件物品,輸入用空格隔開;要么增加幾個用例來體現輸入的格式,而不是這樣模糊的描述。
最后,自己寫輸入要注意的是,讀取n后需要getchar()來去掉n后面的回車,否則getline讀取的第一個字符串就是回車字符。
代碼
#include <iostream> #include <string> #include <sstream> #include <vector> using namespace std; string t[3] = {"ak", "m4a1", "skr"}; bool check(string &s) {for(int i = 0;i < 3;i++) {if(s == t[i]) {return true;}}return false; } int main() {int n;std::vector<std::vector<std::string>> vec;std::cin>>n;string s;int res = 0;getchar();for(int i = 0;i < n;i++) {getline(cin,s);stringstream ss(s);string x;while(ss>>x) {if(check(x)) {res++;break;}}}std::cout<<res<<std::endl;return 0; }2.鬼畫符門
題目描述
鬼畫符門,每年都會統計自己宗門鬼畫符消耗的數量,往年一直是大師兄管理, 但是這次鬼藝接手了, 你能幫鬼藝寫一個
程序統計每年消耗數量最多的鬼畫符嗎?
分析
本題考查hash的簡單應用。第一遍遍歷字符串數組統計出每個字符串出現的次數,同時更新下出現最多的鬼畫符次數。第二次遍歷字符串數組,一旦遍歷到某個鬼畫符出現的次數等于最多的次數,返回該字符串即可。
代碼
#include <iostream> #include <string> #include <sstream> #include <unordered_map> #include <algorithm> #include <vector> using namespace std; unordered_map<string,int> m; int main() {int n;std::cin>>n;vector<string> t;string s,res;for(int i = 0;i < n;i++) {cin>>s;t.push_back(s);}int p = 0;for(auto x : t) {m[x]++;p = max(p, m[x]);}for(auto x : t) {if(m[x] == p) {res = x;break;}}cout<<res<<endl;return 0; }3.收件郵箱
題目描述
已知字符串str,str表示郵箱的不標準格式。 其中”.”會被記錄成”dot”,”@”記錄成”at”。 寫一個程序將str轉化成可用
的郵箱格式。(可用格式中字符串中除了開頭結尾所有”dot”,都會被轉換,”at”只會被轉化一次,開頭結尾的不轉化)
分析
這題也是之前每日一題里面的題目,稍微需要多一點判斷的模擬題,考察對字符串的處理。
可以用res來記錄最終的結果。逐位遍歷str,然后進行判斷:
- 如果str[i]是‘d’,如果i不是在開頭,也不是在str的倒數第三位,并且后兩位是‘o’和’t‘,那么res需要追加上’.'。
- 如果str[i]是’a’,還是要判斷是否在開頭或者結尾,不在的話后面的字符是’t’,并且之前沒有轉化過才給res追加上’@'。
- 如果str[i]不是‘a’或者’d’,或者是前兩種分支的else情況,直接追加到res末尾即可。
本題對字符串的模擬并不復雜,主要需要細心的地方是判斷后面的字符時需要注意下標不要越界,以及判斷為dot或者at后需要跳幾位再繼續遍歷,最后就是在考慮到at只轉化一次的基礎上注意開頭的at不轉化的規則。
代碼
#include <iostream> #include <string> #include <sstream> #include <vector> using namespace std; std::string solution(std::string str){std::string res;int n = str.size();bool flag = true;for(int i = 0;i < n;i++) {if(str[i] == 'd') {if(i && i < n - 3 && str[i+1]=='o' && str[i+2]=='t') {res += ".";i += 2;}else res += "d";}else if(str[i] == 'a' && flag) {if(i && i < n - 2 && str[i+1] == 't') {res += "@";flag = false;i++;}else res += "a";}else res += str[i];}return res; } int main() {std::string str;std::cin>>str;std::string result = solution(str);std::cout<<result<<std::endl;return 0; }4.最長遞增的區間長度
題目描述
給一個無序數組,求最長遞增的區間長度。如:[5,2,3,8,1,9] 最長區間 2,3,8 長度為 3
分析
這題也是每日一題的題目,第一次看見這題還以為用例有問題,因為第一印象是求最長遞增子序列,然后覺得用例的最初遞增子序列是2,3,8,9,長度是4。寫了個LIS的代碼提交上去WA了。再次讀題發現求的是最長連續遞增子序列。
一般算法題里不連續的叫做子序列,連續的叫做子串或者連續子序列,看見區間就沒有反應過來。既然是求最長連續子序列長度,那么解法就比LIS問題更簡單了。不用去考慮雙指針或者DP的思想,直接模擬解決即可。
設res為當前遍歷過的序列的最長連續遞增子序列的長度,cnt是當前遍歷到的最長連續遞增子序列的長度,或者說是以當前遍歷到的元素為末尾的最長連續遞增子序列的長度。具體遍歷過程就是:遍歷當前元素,如果當前元素大于前一個元素,cnt++,否則cnt置為1表示以當前元素結尾的最長連續遞增子序列的長度是1。每次cnt置1的時候以及遍歷結束的時候嘗試更新下最后的結果res即可。
遍歷過程中蘊含DP的思想,即f[i]表示以第i個元素結尾的最長連續遞增子序列的長度,最終的答案res = max(f[i])。由于在遍歷過程中就更新了res,所以dp數組簡化為了變量cnt。當然,寫代碼時候不用考慮背后的DP思想,也是可以很快寫出來的。
代碼
#include <iostream> #include <algorithm> #include <string> #include <sstream> #include <vector> using namespace std; const int N = 10005; int f[N]; int solution(int n, std::vector<int>& vec){int res = 1;int cnt = 1;for(int i = 0;i < n;i++) {if(i && vec[i] > vec[i - 1]) cnt++;else {res = max(res,cnt);cnt = 1;}}res = max(res,cnt);return res; } int main() {int n;std::vector<int> vec;std::cin>>n;std::string line_0, token_0;getline(std::cin >> std::ws,line_0);std::stringstream tokens_0(line_0);while(std::getline(tokens_0, token_0, ' ')){vec.push_back(std::stoi(token_0));}int result = solution(n,vec);std::cout<<result<<std::endl;return 0; }總結
以上是生活随笔為你收集整理的CSDN竞赛6期题解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot将图片/文件传至前端
- 下一篇: PostgreSQL psql 命令语法