2013 ACM/ICPC 亚洲区 杭州站
题目链接 2013杭州区域赛
Problem A
Problem B
这题我用的是SPFA+ mask dp
首先跑5次SPFA:
1次是求出每个起点和其他所有点的最短距离
4次是求出每个输入的点和其他所有点的最短距离
然后就是dp
设dp[mask][i]为,mask状态下,以i为终点的最优方案
然后做一遍状压DP即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 103; const int M = 1e4 + 10; const int dx[] = {1, 0, -1, 0}; const int dy[] = {0, 1, 0, -1}; bool inqueue[M], fl; int c[N][N], f[6][6], a[M], d[M], dp[101][6]; char s[N][N]; int cnt, n, m, k; vector <int> v[M]; inline void addedge(int x, int y){ v[x].push_back(y); v[y].push_back(x); } void SPFA(int s){ memset(inqueue, false, sizeof inqueue); rep(i, 1, cnt) d[i] = 1 << 29; d[s] = 0; queue <int> q; q.push(s); while (!q.empty()){ int x = q.front(); q.pop(); inqueue[x] = false; for (auto u : v[x]){ if (d[u] > d[x] + 1){ d[u] = d[x] + 1; if (!inqueue[u]){ inqueue[u] = true; q.push(u); } } } } } int main(){ while (~scanf("%d%d", &n, &m), n + m){ rep(i, 1, n) scanf("%s", s[i] + 1); cnt = 0; rep(i, 1, n) rep(j, 1, m) c[i][j] = ++cnt; scanf("%d", &k); rep(i, 1, n) rep(j, 1, m) if (s[i][j] == '@'){ a[k] = c[i][j]; s[i][j] = '.'; break; } rep(i, 0, k - 1){ int x, y; scanf("%d%d", &x, &y); a[i] = c[x][y]; } rep(i, 0, n * m + 1) v[i].clear(); rep(i, 1, n){ rep(j, 1, m) if (s[i][j] == '.'){ rep(k, 0, 3){ int x = i + dx[k], y = j + dy[k]; if (s[x][y] == '.'){ addedge(c[i][j], c[x][y]); } } } } SPFA(a[k]); rep(i, 0, k) rep(j, 0, k) f[i][j] = 1 << 29; rep(i, 0, k){ SPFA(a[i]); rep(j, 0, k) if (i == j) f[i][j] = 0; else f[i][j] = d[a[j]]; } rep(i, 0, 53) rep(j, 0, 5) dp[i][j] = 1 << 29; rep(i, 0, k - 1) dp[1 << i][i] = f[i][k]; rep(i, 1, ((1 << k) - 1)){ if (__builtin_popcount(i) != 1){ rep(j, 0, k - 1) if ((i >> j) & 1){ rep(l, 0, k - 1) if (((i >> l) & 1) && (j != l)){ dp[i][j] = min(dp[i][j], dp[i ^ (1 << j)][l] + f[j][l]); } } } } int ans = 1 << 30; rep(i, 0, k - 1) ans = min(ans, dp[(1 << k) - 1][i]); printf("%d\n", ans < 1e6 ? ans : -1); } return 0; }
Problem C
跟着题意模拟一遍
关键是那个旋转要一次性写对
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 41; int a[N][N], b[N][N]; int n; int ans; void solve(){ int c[N][N]; memset(c, 0, sizeof c); rep(i, 1, n) rep(j, 1, n) c[i][j] = a[j][n - i + 1]; rep(i, 1, n) rep(j, 1, n) a[i][j] = c[i][j]; } int main(){ while (~scanf("%d", &n), n){ rep(i, 1, n) rep(j, 1, n) scanf("%d", &a[i][j]); rep(i, 1, n) rep(j, 1, n) scanf("%d", &b[i][j]); ans = 0; rep(p, 1, 4){ solve(); int now = 0; rep(i, 1, n) rep(j, 1, n) if (a[i][j] == b[i][j]) ++now; ans = max(ans, now); } printf("%d\n", ans); } return 0; }
Problem D
Problem E
Problem F
Problem G
Problem H
Problem I
Problem J
Problem K