比赛链接:Here

A、B题跳过

C - chokudai

题意:

给出一个字符串,问有多少个字串能构成 chokudai


这道题算是一个简单DP,只要计算某个位置对构成 chokudai 的贡献值即可

AtCoder Beginner Contest 211 (C ~ E) - 图1

AtCoder Beginner Contest 211 (C ~ E) - 图2

  1. const int mod = 1e9 + 7;
  2. ll f[10] = {1};
  3. int main() {
  4. cin.tie(nullptr)->sync_with_stdio(false);
  5. string s, t = " chokudai";
  6. cin >> s;
  7. int n = s.length();
  8. for (int i = 0; i < n; ++i)
  9. for (int j = 1; j <= 8; ++j)
  10. if (s[i] == t[j]) f[j] = (f[j] + f[j - 1]) % mod;
  11. cout << f[8] % mod;
  12. }

D - Number of Shortest paths

题意:

高桥王国有 AtCoder Beginner Contest 211 (C ~ E) - 图3 个城市和 AtCoder Beginner Contest 211 (C ~ E) - 图4 个双向道路

请问有多少条最短路径能从城市 AtCoder Beginner Contest 211 (C ~ E) - 图5 走到城市 AtCoder Beginner Contest 211 (C ~ E) - 图6


简单跑一下BFS,同时维护各个城市到城市AtCoder Beginner Contest 211 (C ~ E) - 图7 的最短情况,用DP维护路径数

  1. const int N = 2e5 + 10;
  2. const int mod = 1e9 + 7;
  3. vector<int>e[N];
  4. int dp[N], dist[N];
  5. int main() {
  6. cin.tie(nullptr)->sync_with_stdio(false);
  7. memset(dist, -1, sizeof(dist));
  8. int n, m;
  9. cin >> n >> m;
  10. for (int i = 1, a, b; i <= m; ++i) {
  11. cin >> a >> b;
  12. e[a].push_back(b);
  13. e[b].push_back(a);
  14. }
  15. queue<int>q;
  16. dist[1] = 0, dp[1] = 1, q.push(1);
  17. while (q.size()) {
  18. int u = q.front(); q.pop();
  19. for (int v : e[u]) {
  20. if (dist[v] == -1) {
  21. dp[v] = dp[u];
  22. dist[v] = dist[u] + 1;
  23. q.push(v);
  24. } else if (dist[u] + 1 == dist[v]) dp[v] = (dp[v] + dp[u]) % mod;
  25. }
  26. }
  27. cout << dp[n];
  28. }

E - Red Polyomino


AtCoder Beginner Contest 211 (C ~ E) - 图8 个方格中的K个方格的选择数是 AtCoder Beginner Contest 211 (C ~ E) - 图9 ,由于 AtCoder Beginner Contest 211 (C ~ E) - 图10 ,因此直接暴力是不可能的了。

但是,由于红色方块相互连接,我们可以预测满足条件的组合数量很少。

所以可以跑枚举红色方块连接模式的 DFS(深度优先搜索)就足够了。

  1. using ull = unsigned long long;
  2. int n, k, ans;
  3. char s[10][10];
  4. set<ull>mp;
  5. ull S;
  6. bool check(int x, int y) {
  7. if (s[x][y] == '#' || (S & 1ull << (x * n + y))) return false;
  8. if (x > 0 and (S & 1ull << ((x - 1) * n + y))) return true;
  9. if (x < n - 1 and (S & 1ull << ((x + 1) * n + y))) return true;
  10. if (y > 0 and (S & 1ull << (x * n + y - 1))) return true;
  11. if (y < n - 1 and (S & 1ull << (x * n + y + 1))) return true;
  12. return false;
  13. }
  14. void dfs(int d) {
  15. if (mp.find(S) != mp.end())return ;
  16. mp.insert(S);
  17. if (d == k) {ans++; return ;}
  18. for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) {
  19. if (check(i, j)) {
  20. S ^= (1ull << (i * n + j));
  21. dfs(d + 1);
  22. S ^= (1ull << (i * n + j));
  23. }
  24. }
  25. }
  26. int main() {
  27. //cin.tie(nullptr)->sync_with_stdio(false); // 需注释,cin 与 scanf 冲突
  28. cin >> n >> k;
  29. for (int i = 0; i < n; ++i) scanf("%s", s[i]);
  30. for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) {
  31. if (s[i][j] != '#') {
  32. S ^= (1ull << (i * n + j));
  33. dfs(1);
  34. S ^= (1ull << (i * n + j));
  35. }
  36. }
  37. cout << ans << "\n";
  38. }