1002.Blow up the Enemy
先把最优的武器选出来,花最少时间能打死对面那种(不止一个)
父亲想赢的话就只有赌中这些最优的武器概率为cnt/n,选出来了也只有1/2的概率赢
最后我赢的概率就是父亲输的概率 ,1-cnt/2n
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) int n, a, b; int tmp, cnt, mt; inline void solve() { cin >> n; mt = 1e9; rep(i, 1, n) { cin >> a >> b; tmp = 100 / a; if (100 % a == 0) tmp--; tmp *= b; if (tmp == mt) cnt++; else if (tmp < mt) { cnt = 1; mt = tmp; } } cout << 1.0 * (2 * n - cnt) / (2 * n) << endl; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t = 1; cin >> t; while (t--) { solve(); } }
1004.Deliver the Cake
最短路问题,经过某些村庄必须停留换手。。
直接上Dijkstra,考虑经过M的时候把他拆成l,r两个点。
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) struct edges { int to, next, w; } e[400010]; int id, head[100010]; inline void add(int x, int y, int w) { e[++id].w = w; e[id].to = y; e[id].next = head[x]; head[x] = id; } struct node { unsigned long long u, d, flag; bool operator<(const node &f) const { return d > f.d; } }; priority_queue<node> q; unsigned long long n, m, s, v, x; char str[100010]; int dir[100010], vis[100010][3]; unsigned long long dis[100010][3]; inline void solve() { cin >> n >> m >> s >> v >> x; cin >> str; rep(i, 0, n - 1) if (str[i] == 'M') dir[i + 1] = 0; else if (str[i] == 'L') dir[i + 1] = 1; else if (str[i] == 'R') dir[i + 1] = 2; id = 0; memset(e, 0, sizeof(e)); rep(i, 1, n) { dis[i][1] = dis[i][2] = 1e16; head[i] = vis[i][1] = vis[i][2] = 0; } int a, b, w; rep(i, 1, m) { cin >> a >> b >> w; add(a, b, w); add(b, a, w); } if (dir[s]) { q.push((node){s, 0, dir[s]}); dis[s][dir[s]] = 0; } else { q.push((node){s, 0, 1}); q.push((node){s, 0, 2}); dis[s][1] = dis[s][2] = 0; } while (!q.empty()) { s = q.top().u; int flag = q.top().flag, flag2; q.pop(); if (vis[s][flag]) continue; vis[s][flag] = 1; for (int i = head[s]; i; i = e[i].next) { ll tmp = dis[s][flag] + e[i].w; flag2 = dir[e[i].to]; if (flag2) { if (flag != flag2) tmp += x; if (!vis[e[i].to][flag2] && dis[e[i].to][flag2] > tmp) { dis[e[i].to][flag2] = tmp; q.push((node){e[i].to, dis[e[i].to][flag2], flag2}); } } else { if (!vis[e[i].to][flag] && dis[e[i].to][flag] > tmp) { dis[e[i].to][flag] = tmp; q.push((node){e[i].to, dis[e[i].to][flag], flag}); } if (!vis[e[i].to][3 - flag] && dis[e[i].to][3 - flag] > tmp + x) { dis[e[i].to][3 - flag] = tmp + x; q.push((node){e[i].to, dis[e[i].to][3 - flag], 3 - flag}); } } } } if (dir[v]) cout << dis[v][dir[v]] << endl; else cout << min(dis[v][1], dis[v][2]) << endl; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t = 1; cin >> t; while (t--) { solve(); } }
1005.Equal Sentences
每个单词出现的位置不能差超过1的长度,这就限制了只能相邻的两个单词交换。
相同的单词不能交换,那就记录下当前位置种类数。
dp[i][0]表示与上一个位置不交换,dp[i][0] = dp[i-1][0] + dp[i-1][1]
dp[i][1]表示与上一个位置交换,如果当前单词与上一个相等,则dp[i][1]=0,不相等dp[i][1] = dp[i-1][0]
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) int mod = 1e9 + 7; int n; char a[100010][15]; int vis[100010], dp[100010][2]; inline void solve() { memset(a, 0, sizeof(a)); cin >> n; rep(i, 1, n) { scanf("%s", a[i]); dp[i][0] = dp[i][1] = 0; vis[i] = strcmp(a[i], a[i - 1]) == 0; } dp[1][0] = 1; rep(i, 2, n) { dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % mod; dp[i][1] = vis[i] ? 0 : dp[i - 1][0]; } cout << (dp[n][0] + dp[n][1]) % mod << endl; } int main() { // ios_base::sync_with_stdio(0); // cin.tie(0); // cout.tie(0); int t = 1; cin >> t; while (t--) { solve(); } }
1007.Go Running
每个人只能往某一个方向跑,告诉你 t 时刻在 x 位置有人,问最少有多少个人。
由于只能往一个方向跑,那么x和t和或者差相等的一些点可以分为一个人,
把(t,x)点对画在坐标轴上,一条斜率为1或者-1的直线就表示一个人,
坐标轴旋转一下,就简化成画多少条平行于坐标轴的直线能将平面上的点覆盖,
这就简化成了二分图的经典模型,将每个点横坐标向纵坐标连边,求最大匹配。
匈牙利算法复杂度O(n2),这里用网络流dinic O(n√n)的方式解决
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) struct edge { int to, next, w; } e[600100]; int id, head[200100]; void add(int x, int y) { e[++id] = (edge){y, head[x], 1}; head[x] = id; e[++id] = (edge){x, head[y], 0}; head[y] = id; } int n, a[100010], b[100010], mia[100010], mib[100010]; int s, v, ans; int dis[200100]; queue<int> q; bool bfs() { rep(i, 1, v) dis[i] = -1; dis[s] = 0; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i; i = e[i].next) if (dis[e[i].to] == -1 && e[i].w > 0) { dis[e[i].to] = dis[u] + 1; q.push(e[i].to); } } return dis[v] != -1; } int dfs(int u, int limit) { if (u == v) return limit; int flow = 0, tmp = 0; for (int i = head[u]; i; i = e[i].next) { if (dis[e[i].to] == dis[u] + 1 && e[i].w > 0) { tmp = dfs(e[i].to, min(limit, e[i].w)); if (!tmp) continue; limit -= tmp; flow += tmp; e[i].w -= tmp; e[i ^ 1].w += tmp; if (!limit) break; } } return flow; } inline void solve() { cin >> n; id = 1; memset(head, 0, sizeof(head)); memset(e, 0, sizeof(e)); int aa, bb; rep(i, 1, n) { cin >> aa >> bb; mia[i] = a[i] = bb + aa; mib[i] = b[i] = bb - aa; } sort(mia + 1, mia + n + 1); sort(mib + 1, mib + n + 1); int na = unique(mia + 1, mia + n + 1) - mia - 1; int nb = unique(mib + 1, mib + n + 1) - mib - 1; s = na + nb + 1; v = s + 1; map<int, int> mpa, mpb; rep(i, 1, na) { mpa[mia[i]] = i; add(s, i); } rep(i, 1, nb) { mpb[mib[i]] = i + na; add(i + na, v); } rep(i, 1, n) add(mpa[a[i]], mpb[b[i]]); ans = 0; while (bfs()) ans += dfs(s, 1e9); cout << ans << endl; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t = 1; cin >> t; while (t--) { solve(); } }
1011.Kindergarten Physics
签到题!算得正嗨,队友说直接输出(d-1).9999999
题解也是直接输出d
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) int a, b, c, d; inline void solve() { cin >> a >> b >> c >> d; cout << c - 1 << ".999999999 "; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t = 1; cin >> t; while (t--) { solve(); } }
1012.Last Problem
构造题,要在(x,y)位置填n,必须要在四周填n-1,n-2,n-3,n-4。
暴搜,让n-1,n-4在两侧,n-2,n-3在两侧可以减少重复填数的次数。
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) typedef pair<int, int> pii; #define mk(x, y) make_pair(x, y) int n; map<pii, int> mp; inline void dfs(int x, int y, int k) { if (k > 1 && mp[mk(x + 1, y)] != k - 1) dfs(x + 1, y, k - 1); if (k > 2 && mp[mk(x, y + 1)] != k - 2) dfs(x, y + 1, k - 2); if (k > 3 && mp[mk(x, y - 1)] != k - 3) dfs(x, y - 1, k - 3); if (k > 4 && mp[mk(x - 1, y)] != k - 4) dfs(x - 1, y, k - 4); mp[mk(x, y)] = k; cout << x << " " << y << " " << k << endl; } inline void solve() { cin >> n; dfs(0, 0, n); } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t = 1; // cin >> t; while (t--) { solve(); } }