第十三次CCF-CSP認證
- 跳一跳
- 滿分題解
- 碰撞的小球
- 滿分題解
- 遇到的問題
- 棋局評估
- 滿分題解
跳一跳
題目鏈接
滿分題解
沒什么好說的 基本思路就是如何用代碼翻譯題目所給的一些限制,以及變量應該如何更新,沒像往常一樣給一個n,怎么讀入數據,但是總之
這題對于我就倆字 :《凌 駕》
#include <bits/stdc++.h>
using namespace std;
const int N =40;
int s[N];
int main()
{int i=0;s[0]=-1;//我的小細節while(s[i]!=0){cin>>s[i+1];i++;}//讀入跳躍數組//如果是第一次跳躍或者上一次跳躍不是中心計2分int grade=0;int sum=2;for(int j=1;j<i+1;j++){while(s[j]==2){if(j==1 || s[j-1]==1 && j>1){grade+=2;sum=2;j++;}else if(s[j-1]==2 && j>1){sum+=2;grade+=sum;j++;}}if(s[j]!=0)grade++;}cout<<grade;
}
碰撞的小球
樣例:
滿分題解
遇到的問題
一開始感覺自己無敵了呀 一看這題目這么長 感覺這題 換做一個星期之前直接copy評論區了,后來通過慢慢分析基本上思路就清晰了,寫完感覺這代碼非常完美啊,還宏定義了一把,可讀性很高啊,調試的時候樣例也過了,一交發現就過了兩個樣例 我cnm,服了
后來發現:
是我的碰撞判斷不完整:當前代碼只檢查了相鄰小球的碰撞情況,實際上任意兩個小球都可能發生碰撞,如果只檢查初始相鄰的兩個小球是否碰撞,就會遺漏很多可能的碰撞情況。因此,需要使用兩層循環遍歷所有的小球對,以確保檢查到任意兩個小球之間是否發生了碰撞。
#include <iostream>
#include <vector>
using namespace std;#define RIGHT 1
#define LEFT -1struct ball {int div;int pos;
};int main() {int n, L, t;cin >> n >> L >> t; // 讀入 n 個小球,距離長度和時刻vector<ball> balls(n); // 存儲每一個小球的信息for (int i = 0; i < n; i++) {int index;cin >> index;balls[i].pos = index;balls[i].div = RIGHT; // 一開始統一向右邊走} // 初始化完成while (t--) {// 小球移動for (int i = 0; i < n; i++) {if (balls[i].div == RIGHT) {balls[i].pos++;} else {balls[i].pos--;}}// 檢查邊界情況for (int j = 0; j < n; j++) {if (balls[j].pos == L) { // 右端點的情況balls[j].div = LEFT;} else if (balls[j].pos == 0) { // 左端點的情況balls[j].div = RIGHT;}}// 檢查小球之間的碰撞情況for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {if (balls[i].pos == balls[j].pos) {balls[i].div = -balls[i].div;balls[j].div = -balls[j].div;}}}}for (int i = 0; i < n; i++) {cout << balls[i].pos << " ";}cout << endl;return 0;
}
棋局評估
樣例:
滿分題解
題目非常好理解就是大家都玩過的井字棋,這題感覺更重思維,dfs很少,以我現在的水平是可以獨立寫一下的,明天再學一學
作者:cyzh
代碼鏈接
#include<bits/stdc++.h>
using namespace std;int g[4][4];
int tt, oo;//數據組數,空格個數//判斷是否有人獲勝,如果Alice獲勝返回1,如果Bob獲勝返回2,否則返回0
int check(){for(int i = 0; i < 3; i++){if(g[i][0] == g[i][1] && g[i][1] == g[i][2] && g[i][2]) return g[i][2];if(g[0][i] == g[1][i] && g[1][i] == g[2][i] && g[2][i]) return g[2][i];}if(g[0][0] == g[1][1] && g[1][1] == g[2][2] && g[2][2]) return g[2][2];if(g[0][2] == g[1][1] && g[1][1] == g[2][0] && g[1][1]) return g[1][1];return 0;
}//返回值為題目要求的答案,u 表示剩下0的個數
int dfs(int u){if(check()){if(check() == 1) return u + 1;//Alice已經贏了else return - u - 1;//Bob已經贏了}if(u == 0) return 0;//沒有格子可以下了//f11表示Alice贏的最優決策,f22表示Bob贏的最優決策//f12表示Alice贏的次優決策,f21表示Bob贏的次優決策/*為什么要分4個呢,因為如果這一步是Bob下的話如果他能贏 返回f22Bob如果自己贏不了 他會先想到是否能平局 返回0Bob如果不能平局 他會想到怎么多拖一點時間, 返回 f12同理如果這一步是Alice下的話 如果他能贏 返回f11Alice如果自己贏不了 他會先想到是否能平局 返回0Alice如果不能平局 他會想到怎么多拖一點時間, 返回 f21*/int f12 = 20, f21 = -20, f0 = 0, f11 = 0, f22 = 0, tmp;for(int i = 0; i < 3; i++)for(int j = 0; j < 3; j++){if(!g[i][j]){g[i][j] = !(u%2) + 1, tmp = dfs(u - 1), g[i][j] = 0;//dfsif(tmp == 0) f0 = 1;//如果可以平局, f0 = tureelse if(tmp < 0) f22 = min(f22, tmp), f21 = max(f21, tmp);//維護f22, f21else if(tmp > 0) f11 = max(f11, tmp), f12 = min(f12, tmp);//同理}}if(u % 2 && f11) return f11;//這一步是Alice來下 && Alice可以贏else if(!(u % 2) && f22 < 0) return f22;//這一步是Bob來下 && Bob可以贏if(f0) return 0;//可以平局if(u % 2) return f21;//這一步是Alice來下 && Alice 只能讓Bob贏return f12;
}int main(){cin >> tt;while(tt--){oo = 0;for(int i = 0; i < 9; i++) cin >> g[i/3][i%3], oo += !g[i/3][i%3];//輸入cout << dfs(oo) << endl;}
}