比賽地址c++
題目連接
⭐spa
題目:
給定一個\(n\times m\)的點陣,ZYT和LBC輪流走,ZYT先走,每一個人每次只能向上下左右四個方向走一次,且不能去到已經走過的點,ZYT先走,沒法走動的人輸,問這局遊戲的勝者是誰code
解析:
因爲不能走到已經去過的點,因此這張圖裏沒有環,因此是一顆生成樹,那麼只要判斷\(n*m\)的奇偶性便可blog
#include<bits/stdc++.h> using namespace std; int a, b; int main() { scanf("%d%d", &a, &b); printf("%s", a * b & 1 ? "NO" : "YES"); }
題目連接
⭐排序
題目:
總共有4套牌,牌的大小爲\(2\sim 10\),如今如有如下比較規則,對兩副手牌\((a_1,b_1)(a_2,b_2)\)進行比較隊列
解析:
根據題意暴力if
判斷遊戲
#include<cstdio> #include<algorithm> using namespace std; int main() { int T; scanf("%d", &T); int a[2], b[2]; while (T--) { scanf("%d%d%d%d", &a[0], &b[0], &a[1], &b[1]); if (a[0] > b[0]) swap(a[0], b[0]); if (a[1] > b[1]) swap(a[1], b[1]); if (a[0] == a[1] && b[0] == b[1]) printf("tie"); else if (a[0] == 2 && b[0] == 8) printf("first"); else if (a[1] == 2 && b[1] == 8) printf("second"); else if (a[0] == b[0]) { if (a[1] != b[1] || a[0] > a[1]) printf("first"); else printf("second"); } else if (a[1] == b[1]) printf("second"); else { int c[2] = {(a[0] + b[0]) % 10, (a[1] + b[1]) % 10}; if (c[0] == c[1]) printf("%s", b[0] > b[1] ? "first" : "second"); else printf("%s", c[0] > c[1] ? "first" : "second"); } printf("\n"); } }
題目連接
⭐⭐get
題目:
給定一個三維座標系中的四個固定點\(A,B,C,D\),有兩個任意位置的點\(P_1,P_2\),須要知足\(|AP_1|\ge k_1|BP_1|,|CP_2|\ge k_2|DP_2|\),則\(P_1,P_2\)可移動範圍的交集的空間體積是多少it
解析:
根據\(P_1,P_2\)的範圍條件限制,不難看出他的活動範圍在一個阿波羅尼奧斯圓內部,這樣只要套一個圓相交求相交體積的板子便可(下給出推導過程,以\(P_1(x_0,y_0,z_0)\)爲例,注意\(1-k_1^2<0\))
io
#include<bits/stdc++.h> using namespace std; const double pi = acos(-1); const double eps = 1e-9; const int inf = 1e9 + 7; typedef struct { double x, y, z, r; }Point; Point s[2]; //兩點之間距離 double dis(Point p, Point q) { double ans = sqrt((p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y) + (p.z - q.z) * (p.z - q.z)); return ans; } double calV(Point p) { return (4.0 / 3) * pi * (p.r * p.r * p.r); } double solve(Point a, Point s) { if (s.r < a.r)swap(a, s); double ans = 0; double d = dis(s, a); if (d >= a.r + s.r + eps)ans = 0; else if (d + a.r <= s.r)ans += calV(a); else if (d + s.r <= a.r)ans += calV(s); else if (fabs(s.r - a.r) <= d + eps && d <= a.r + s.r + eps) { double co = (s.r * s.r + d * d - a.r * a.r) / (2.0 * d * s.r); double h = s.r * (1 - co); ans += pi * h * h * (s.r - h / 3.0); co = (a.r * a.r + d * d - s.r * s.r) / (2.0 * d * a.r); h = a.r * (1 - co); ans += pi * h * h * (a.r - h / 3.0); } return ans; } double get_res() { double ans = 0; double d = dis(s[0], s[1]); if (d >= s[0].r + s[1].r) { return 0; } else if (d + s[1].r <= s[0].r) { ans += (4.0 / 3) * pi * s[1].r * s[1].r * s[1].r; } else { double co = (s[0].r * s[0].r + d * d - s[1].r * s[1].r) / (2.0 * d * s[0].r); double h = s[0].r * (1 - co); ans += (1.0 / 3) * pi * (3.0 * s[0].r - h) * h * h; co = (s[1].r * s[1].r + d * d - s[0].r * s[0].r) / (2.0 * d * s[1].r); h = s[1].r * (1 - co); ans += (1.0 / 3) * pi * (3.0 * s[1].r - h) * h * h; } return ans; } int main() { int T; double a[12]; double k[2]; scanf("%d", &T); while (T--) { memset(s, 0, sizeof(s)); for (int i = 0; i < 12; ++i) scanf("%lf", a + i); for (int i = 0; i < 2; ++i) scanf("%lf", k + i); for (int i = 0; i < 2; ++i) { s[i].x = (k[i] * k[i] * a[6 * i + 3] - a[6 * i]) / (k[i] * k[i] - 1); s[i].y = (k[i] * k[i] * a[6 * i + 4] - a[6 * i + 1]) / (k[i] * k[i] - 1); s[i].z = (k[i] * k[i] * a[6 * i + 5] - a[6 * i + 2]) / (k[i] * k[i] - 1); for (int j = 0; j < 3; ++j) s[i].r += k[i] * k[i] * (a[6 * i + j] - a[6 * i + j + 3]) * (a[6 * i + j] - a[6 * i + j + 3]); s[i].r = sqrt(s[i].r / (k[i] * k[i] - 1) / (k[i] * k[i] - 1)); } printf("%.3f\n", solve(s[0], s[1])); } return 0; }
題目連接
⭐⭐⭐⭐⭐
題目:
將\(n\)個區間分紅\(k\)組,每組取交集,求交集之和的最大值
解析:
狀態轉移式即爲從以前某個區間(包括自身)做爲這個分組中的頭,當前枚舉區間做爲分組的尾,每次首右端點,尾左端點作差即爲這之間合爲一組的貢獻(因爲左端點按增序排列,因此交集愈來愈小能夠直接計算)再加上頭以前的區間分紅\(i-1\)組時的\(dp\)值,這個最大值能夠用優先隊列進行維護
補充:
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> pi; const int maxn = 5e3 + 5; pi a[maxn], small[maxn]; int big[maxn]; int sc, bc; int main() { int n, k; scanf("%d%d", &n, &k); for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].first, &a[i].second); sort(a + 1, a + n + 1); int mn = 0x3f3f3f3f; for (int i = n; i; --i) { if (a[i].second < mn) { mn = a[i].second; small[sc++] = a[i]; } else big[++bc] = a[i].second - a[i].first; } sort(big + 1, big + bc + 1, greater<int>()); for (int i = 1; i <= bc; ++i) big[i] += big[i - 1]; reverse(small, small + sc); vector<vector<int>> dp(2, vector<int>(sc + 1)); dp[0].assign(n + 1, -0x3f3f3f3f); dp[0][0] = 0; deque<int> q; int ans = 0; for (int i = 1; i <= k; ++i) { dp[1].assign(n + 1, -0x3f3f3f3f); q.clear(); for (int j = i - 1; j < sc; ++j) { while (!q.empty() && small[q.back()].second + dp[0][q.back()] <= small[j].second + dp[0][j]) q.pop_back(); q.emplace_back(j); while (!q.empty() && small[q[0]].second <= small[j].first) q.pop_front(); dp[1][j + 1] = dp[0][q[0]] + small[q[0]].second - small[j].first; } if (bc >= k - i) ans = max(ans, dp[1][sc] + big[k - i]); swap(dp[0], dp[1]); } printf("%d", ans); }
題目連接
⭐⭐⭐
題目:
給出兩張圖並排放置,大小均爲\(20\times 20\),其中有一些點上有阻礙物,如今兩隻企鵝分別要從\((20,20)\rightarrow(1,20),(20,1)\rightarrow(1,1)\),他們同時出發,接受相同指令,但移動方向知足下列要求
如今須要給出兩隻企鵝同時到達終點的最小距離以及距離
解析:
假如只有一張圖,那很顯然用BFS能夠馬上求得結果,有兩張圖的時候,則考慮將兩張圖的位置組合起來看做是一張大圖的某個點,這個點由一個四維座標描述,前兩維表明左邊企鵝的座標,後兩維表明右邊企鵝的座標,跑一下BFS便可
#include<bits/stdc++.h> using namespace std; bool flag; int dir1[4][2] = { 1,0,0,-1,0,1,-1,0 }; int dir2[4][2] = { 1,0, 0,1,0,-1,-1,0 }; char ch[4] = { 'U','R','L' ,'D' }; int bas = 20; char mp1[20][25], mp2[20][25]; int path[405][405]; pair<int, int> tp[405][405]; pair<int, int> p; queue<pair<int, int>> q; int f(int x, int y) { return x * bas + y; } void get(int& x, int& y, int z) { x = z / bas, y = z % bas; } bool check(int x1, int y1) { return x1 >= 0 && x1 < 20 && y1 >= 0 && y1 < 20; } int cnt = 0; void bfs() { path[f(bas - 1, bas - 1)][f(bas - 1, 0)] = -2; q.push({ f(bas - 1,bas - 1) ,f(bas - 1,0) }); while (!q.empty()) { auto t = q.front(); q.pop(); int x1, x2, y1, y2; get(x1, y1, t.first), get(x2, y2, t.second); for (int i = 0; i < 4; ++i) { int tx1 = x1 + dir1[i][0], ty1 = y1 + dir1[i][1]; int tx2 = x2 + dir2[i][0], ty2 = y2 + dir2[i][1]; if (mp1[tx1][ty1] == '#' || !check(tx1, ty1)) tx1 = x1, ty1 = y1; if (mp2[tx2][ty2] == '#' || !check(tx2, ty2)) tx2 = x2, ty2 = y2; if (path[f(tx1, ty1)][f(tx2, ty2)] == -1) { path[f(tx1, ty1)][f(tx2, ty2)] = 3 - i; tp[f(tx1, ty1)][f(tx2, ty2)] = t; if (tx1 == 0 && ty1 == bas - 1 && tx2 == 0 && ty2 == 0) return; q.push({ f(tx1, ty1) ,f(tx2, ty2) }); } } } } void P(int x1, int y1, int x2, int y2, int i, int cnt) { mp1[x1][y1] = mp2[x2][y2] = 'A'; int tx1, ty1, tx2, ty2; get(tx1, ty1, tp[f(x1, y1)][f(x2, y2)].first), get(tx2, ty2, tp[f(x1, y1)][f(x2, y2)].second); if (i != -2) { P(tx1, ty1, tx2, ty2, path[f(tx1, ty1)][f(tx2, ty2)], cnt + 1); printf("%c", ch[i]); } else printf("%d\n", cnt); } int main() { //freopen("abc.in", "r", stdin); memset(path, -1, sizeof(path)); for (int i = 0; i < bas; ++i) scanf("%s %s", mp1[i], mp2[i]); bfs(); P(0, bas - 1, 0, 0, path[f(0, bas - 1)][f(0, 0)], 0); for (int i = 0; i < bas; ++i) printf("\n%s %s", mp1[i], mp2[i]); }
題目連接
⭐⭐⭐
題目:
有一個非嚴格單調遞增棧,有\(n\)個未知的數被壓入單調棧內,現給出\(k\)個時刻棧大小,構造出一組合法壓棧序列,沒法構造則返回\(-1\)
解析:
因爲是非嚴格單調遞增棧,因此爲了方便將站內元素彈出,儘量的要保證壓棧元素不一樣。那麼不可貴出假如加入將所給條件按照時刻排序,那麼\(sz_i-sz_{i-1}\le t_i-t_{i-1}\)纔有可能構造合法棧。
若是是一個嚴格單調遞增棧,那麼很容易想到構造棧知足棧內元素爲\(1\sim k\)便可。但對於這道題來講,爲了使得指望插入的值\(x\)從相同變爲不相同時,則要知足前邊出現的值要大於後邊出現的值,這樣才能夠來維護本來的棧大小\(x\),那維護上述的拓撲關係,進行拓撲排序便可
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> pi; const int maxn = 1e6 + 6; pi sor[maxn], a[maxn]; int ans[maxn]; int n, k; bool solve() { scanf("%d%d", &n, &k); for (int i = 1; i <= k; ++i) scanf("%d%d", &a[i].first, &a[i].second); sort(a + 1, a + k + 1); for (int i = 1; i <= k; ++i) { if (a[i].first - a[i - 1].first < a[i].second - a[i - 1].second) return false; for (int j = a[i - 1].first + 1; j < a[i].first; ++j) sor[j] = { j - a[i - 1].first + a[i - 1].second,j }; sor[a[i].first] = { a[i].second,a[i].first }; } for (int j = a[k].first + 1; j <= n; ++j) sor[j] = { j - a[k - 1].first + a[k - 1].second,j }; sort(sor + 1, sor + 1 + n, [](pi a, pi b) { if (a.first != b.first) return a.first < b.first; return a.second > b.second; }); for (int i = 1; i <= n; ++i) ans[sor[i].second] = i; return true; } int main() { if (solve()) for (int i = 1; i <= n; ++i) printf("%d ", ans[i]); else printf("-1"); }