AtCoder Beginner Contest 244题解
A - Last Letter
题目描述:给你一个长度为n
的字符串s
,输出该字符串的最后一个字符。
思路:根据题意模拟即可。
时间复杂度:\(O(n)\)
参考代码:
void solve() {
int n;
string s;
cin >> n >> s;
cout << s.back() << '\n';
return;
}
B - Go Straight and Turn Right
题目描述:你初始时在\((0 , 0)\)位置,朝向\(x\)轴正方向。给你一个长度为\(n\)的命令用字符串\(s\)表示,若\(s_i\)为S
表示朝当前方向前进一个单位;若\(s_i\)为R
表示将方向顺时针旋转90
度。问你的最终位置。
思路:根据题意模拟即可。
时间复杂度:\(O(n)\)
参考代码:
void solve() {
int n;
string s;
cin >> n >> s;
int dire = 0;
int x = 0, y = 0;
for (auto& c : s) {
if (c == 'S') {
if (dire == 0) ++x;
else if (dire == 1) --y;
else if (dire == 2) --x;
else if (dire == 3) ++y;
}
else dire = (dire + 1) % 4;
}
cout << x << " " << y << '\n';
return;
}
C - Yamanote Line Game
题目描述:实现一个简单的交互。
思路:使用set
存储当前还没有使用的数字,然后模拟即可。
时间复杂度:\(O(nlogn)\)
参考代码:
void solve() {
int n;
cin >> n;
set<int>s;
for (int i = 1; i <= 2 * n + 1; ++i) s.insert(i);
int x;
while (!s.empty()) {
x = *s.begin();
s.erase(x);
cout << x << endl;
if (s.empty()) break;
cin >> x;
s.erase(x);
}
return;
}
D - Swap Hats
题目描述:给你两个由R
,G
,B
构成的排列,对于其中一个排列,是否可以通过交换其中两个字符的位置,使得这两个排列相同。若可以输出No
,否则输出Yes
。
思路:根据题意模拟即可。
时间复杂度:\(O(1)\)
参考代码:
void solve() {
vector<string>s(3), t(3);
for (auto& c : s) cin >> c;
for (auto& c : t) cin >> c;
int cnt = 0;
for (int i = 0; i < 3; ++i) cnt += s[i] != t[i];
string res = "No";
if (cnt % 3 == 0) res = "Yes";
cout << res << '\n';
return;
}
E - King Bombee
题目描述:给你一个n
个顶点m
条边的简单无向图。再给你一个k
,和一个起点s
和终点t
,再给你一个顶点x
,保证x
和s , t
都不相同。问从s
出发经过k
条边到达t
的所有路径中x
出现次数为偶数次的路径数。
思路:比较明显的dp
。定义状态\(f_{i , j , op}\)表示经过\(i\)条边到达\(j\),且\(x\)出现次数为\(op\)的路径数。其中\(op\)只有\(0 , 1\)两种取值,显然有转移方程:
时间复杂度:\(O(k(n + m)\)
参考代码:
void solve() {
int n, m, k, s, t, x;
cin >> n >> m >> k >> s >> t >> x;
int u, v;
vector<vector<int>>graph(n + 1);
for (int i = 1; i <= m; ++i) {
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
vector<vector<vector<int>>>f(k + 1, vector<vector<int>>(n + 1, vector<int>(2 , 0)));
f[0][s][0] = 1;
for (int i = 1; i <= k; ++i) {
for (int j = 1; j <= n; ++j) {
for (auto& v : graph[j]) {
if (j == x) f[i][j][1] = (f[i][j][1] + f[i - 1][v][0]) % mod;
else f[i][j][1] = (f[i][j][1] + f[i - 1][v][1]) % mod;
if (j == x) f[i][j][0] = (f[i][j][0] + f[i - 1][v][1]) % mod;
else f[i][j][0] = (f[i][j][0] + f[i - 1][v][0]) % mod;
}
}
}
cout << f[k][t][0] << '\n';
return;
}
F - Shortest Good Path
题目描述:给你\(1\leq n \leq 17\)个顶点\(m\)条边的简单无向图。对于一个长度为\(k\)的路径\((A_1 , A_2 , ...,A_k)\),又有长度为\(n\)的\(01\)串\(s\),若:
- \(s_i\) =
0
,则表示在路径中编号为\(i\)的顶点出现了偶数次 - \(s_i\) =
1
,则表示在路径中编号为i
的顶点出现了奇数次
你的任务是对于\(s\)的所有情况,求出此时路径长度的最短值的和。
思路:为了方便表示,将顶点从\(0\)开始编号,定义\(dis(S , v)\)表示当\(s = S\)且以\(v\)结束时的路径长度的最短值。那么当\(s = S\)时的最短路径就是\(\mathop{min}\limits_{i = 0}^{n - 1}dis(S , i)\)。又想到本题实质是边长为\(1\)求最短路径,自然想到BFS
。初始时\(dis(S_i , v) = inf \;\forall 0 \leq i < 2^n\),起点都初始化为1
,具体看代码吧。
最终答案为:
时间复杂度:\(O(n^2 \times 2^n)\)
参考代码:
void solve() {
int n, m, u, v;
cin >> n >> m;
vector<vector<int>>graph(n);
int N = 1 << n;
const int inf = 0x3f3f3f3f;
vector<vector<int>>dis(N, vector<int>(n, inf));
for (int i = 1; i <= m; ++i) {
cin >> u >> v;
--u; --v;
graph[u].push_back(v);
graph[v].push_back(u);
}
using PII = pair<int, int>;
queue<PII> Q;
for (int i = 0; i < n; ++i) {
Q.push({ 1 << i , i });
dis[1 << i][i] = 1;
}
while (!Q.empty()) {
auto [path, u] = Q.front();
Q.pop();
for (auto& v : graph[u]) {
int nx = path ^ (1 << v);
if (dis[nx][v] < inf) continue;
dis[nx][v] = dis[path][u] + 1;
Q.push({ nx , v });
}
}
long long res = 0;
for (int i = 1; i < N; ++i) {
int mn = inf;
for (int j = 0; j < n; ++j) mn = min(mn, dis[i][j]);
res += mn;
}
cout << res << '\n';
return;
}
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。