【算法题解】2022年第四届河南省CCPC大学生程序设计竞赛(喜提银牌)
文章目錄
- A. Mocha 上小班啦
- E. Serval 的俳句
- F. 集合之和
- G. Mocha 上大班啦
- H. 旋轉水管
比賽題目已上傳到CF:2022 CCPC Henan Provincial Collegiate Programming Contest
比賽排名:Live: 2022年河南省第四屆CCPC大學生程序設計競賽 | RankLand (algoux.org)
喜提銀牌一枚
A. Mocha 上小班啦
這道題我隊友從A題開始往后看,直接發現是道簽到題,上去就開寫,為了防止罰時,我們一起檢查了一遍,不希望在小事在出錯。最后一發A了。哈哈。
思路:構造
- 如果n >10,你們肯定不存在,因為要保證數位中各個數字不相同。
- 如果n <= 10
- n = 1,答案就是0
- n > 1,答案是就是10234…
比賽時AC代碼
#include <bits/stdc++.h> using namespace std; #define int long longsigned main() {int n;cin >> n;if (n > 10)cout << -1 << endl;else{if (n == 1){cout << 1 << endl;}else{cout << "10";for (int i = 2; i < n; i++){cout << i;}cout << endl;}}return 0; }E. Serval 的俳句
過了一會發現E題過了很多,覺得肯定是道簽到題,然后隊長讓我看,我上去一看發現還真是。
思路:貪心
首先,我們需要現在字符串從前到后找到5個相同字符,然后再再剩下的字符串中找7個字符,再然后在剩下的找5個相同字符,最后就找到了一個正確結果。
為啥這樣保證一定正確呢:當時我想的是如果我從字符串的第一位開始找,如果某個字母出現了5次,那么它就一定是最優的,并且只用到了整個字符串最短的部分,那么剩下的同理。
比賽時AC代碼
#include <bits/stdc++.h> using namespace std; #define int long longint cnt[26];signed main() {int n;string s;cin >> n >> s;string res = "";int ok = 0;for (int i = 0; i < n; i++){cnt[s[i] - 'a']++;if (cnt[s[i] - 'a'] == 5 and ok == 0){ok = 1;res += string(5, s[i]);for (int j = 0; j < 26; j++)cnt[j] = 0;}else if (cnt[s[i] - 'a'] == 7 and ok == 1){ok = 2;res += string(7, s[i]);for (int j = 0; j < 26; j++)cnt[j] = 0;}else if (cnt[s[i] - 'a'] == 5 and ok == 2){ok = 3;res += string(5, s[i]);break;}}if (ok == 3)cout << res << endl;elsecout << "none" << endl;return 0; }F. 集合之和
剛開始看這道題的時候感覺這道肯定是個簽到提,但是這個題我們當時都犯渾了,一直在想著怎么找規律,但找的規律都不對,一開始發現了所有奇數都可以構造出來,答案是1 2 3...。然后去想怎么構造偶數的,但發現2和4都構造不出來,是不是有其他偶數也構造不出來,然后去嘗試6,8,10…,等等,就這樣過了一個多小時還沒寫出來,但是都有點崩潰了,我當時內心都已經不能平靜下去了,但已經過了兩三百人了,自己不可能寫不出來吧,然后隊友構造出來了偶數8的構造為1 2 3 5,然后我就想著看看以這個為突破口,然后突然發現它和奇數的規律好像,都是把最后一位加了1,然后我就去測試10,發現就是這樣,當時激動的快哭了。
1 2 3 4
2 3 4 5 6 7 8
1 2 3 5
2 3 4 5 6 7 8 10
然后交了一發A了。激動壞了。差點銀牌都沒了,就卡在這一道簽到題上了。
比賽時AC代碼
#include <bits/stdc++.h> using namespace std; #define int long longsigned main() {int n;cin >> n;if (n & 1){int m = (n + 1) / 2;cout << m << endl;for (int i = 0; i < m; i++){cout << i << " ";}cout << endl;}else{if (n == 2 or n == 4)cout << -1 << endl;else{int m = n / 2;cout << m << endl;for (int i = 1; i < m; i++){cout << i << " ";}cout << m + 1 << endl;}}return 0; }G. Mocha 上大班啦
這道題也是簽到題,隊長先發現了這道題,看過的人也挺多,然后發現和概率有關,頓時就犯了難,因為關于概率的問題都特別難。但是當時已經過了幾十個人了,就想著不可能太難。最后發現概率是個幌子,一點沒用。這道題和概率沒有任何關系。純粹是迷惑人的。最后隊長一發A了。不得不說這題真是妙啊。
思路:枚舉
題目的本意是將n個字符串想與,最后統計字符串中有多少個1,直接枚舉即可。
比賽時AC代碼
#include <bits/stdc++.h> using namespace std; #define int long longstring s[1010]; int cnt[4010]; signed main() {std::ios::sync_with_stdio(false);cin.tie(nullptr);int n, m;cin >> n >> m;for (int i = 1; i <= n; i++){cin >> s[i];for (int j = 1; j <= m; j++){if (s[i][j - 1] == '1')cnt[j]++;}}int q;cin >> q;while (q--){int a, b, l, r, p;cin >> a >> b >> l >> r >> p;}int res = 0;for (int i = 1; i <= m; i++){if (cnt[i] == n)res++;}cout << res << endl;return 0; }H. 旋轉水管
這題是隊長首先看到的,我倆都覺得這題不難,肯定能寫,但當時只有一個人過,并且很多人都wa了,心想不可能這么難吧,然后就開始寫,首先想的是Acwing里的AcWing 1131. 拯救大兵瑞恩這道題,想著還記錄狀態,但寫完了之后提交wa了,然后發現光記錄每個格子的狀態有沒有經歷過不行,因為每個水管必須只能更改一次方向,而且只能走一次,所以不能記錄狀態,然后隊長重寫了一遍,但越來越復雜,寫了四百多行,最后提交還是wa了,然后我突然想到bfs不行,拿dfs可不可以,然后計算了一下復雜度,最后發現由于水管的特殊形態,所以最多只有幾種走法,大約是O(n)的復雜度,所以一定不會超時,然后我就提醒隊長讓他用dfs寫,然后十分鐘不到就寫完并提交A了,我們當時賊激動,太艱難了,終究是過了,一下上到銀牌了。
思路:DFS
每次搜的時候記錄每個位置有沒有走過,如果走過就不能在走,如果出界了也就不能在走了。走完之后還要回溯回來,為了換個路徑尋找。
- 遇到I:只能從上一個過來的方向直走
- 遇到L: 從上一個過來的方向向它的兩邊走
比賽時AC代碼
#include <bits/stdc++.h> using namespace std; #define int long longconst int N = 1e5 + 10; char g[3][N]; bool st[3][N]; int n = 4, m, ex, ey; // 1 是往下走,2是往左走,3是往上走,4是往右走 bool dfs(int x, int y, int k) {if (x == 3 and y == ey)return true;if (x < 1 or x > 2 or y < 1 or y > m or st[x][y])return false;st[x][y] = true;bool t;if (g[x][y] == 'I'){if (k == 1)t = dfs(x + 1, y, 1);else if (k == 2)t = dfs(x, y - 1, 2);else if (k == 3)t = dfs(x - 1, y, 3);elset = dfs(x, y + 1, 4);}else{if (k == 1 or k == 3){t = (dfs(x, y - 1, 2) || dfs(x, y + 1, 4));}else if (k == 2 or k == 4){t = (dfs(x - 1, y, 3) || dfs(x + 1, y, 1));}}st[x][y] = false;return t; }void solve() {cin >> m >> ex >> ey;for (int i = 1; i <= 2; i++){string s;cin >> s;for (int j = 1; j <= m; j++){st[i][j] = false;g[i][j] = s[j - 1];}}if (dfs(1, ex, 1))cout << "YES" << endl;elsecout << "NO" << endl; }signed main() {freopen("in.in", "r", stdin);std::ios::sync_with_stdio(false);cin.tie(nullptr);int t;cin >> t;while (t--){solve();}return 0; }比賽的時候只寫了這五道題,剩下的能補的盡快補上。
總結
以上是生活随笔為你收集整理的【算法题解】2022年第四届河南省CCPC大学生程序设计竞赛(喜提银牌)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: macOS Big Sur到来,为Mac
- 下一篇: Facebook想要成为下一个微信,难!