J - 哈密顿绕行世界问题
分析:
- 找出所有路,使用DFS
- DFS的要点在于寻找终止条件,而这题最后要走到起点,如果以到再次找到起点作为终止条件,在DFS中实现不太方便,所以我们可以判断走到第20个点的时候,它的邻点有没有起点,如果有,说明该条路可以
代码:
#include<iostream> #include<vector> using namespace std; int m, book[21], a, b, c,ans[21],n; vector<int>r[21]; void bfs(int v, int s) { book[v] = 1; ans[s] = v; if (s == 19) { for (int i : r[ans[s]]) { if (i == m) { cout << n++ << ": "; for (int j = 0; j < 20; j++) cout << ans[j] << ' '; cout << m << endl; } } return; } for (int i : r[v]) { if (!book[i]) { bfs(i, s + 1); book[i] = 0; } } } int main() { for (int i = 1; i <= 20; i++) { cin >> a >> b >> c; r[i].push_back(a); r[i].push_back(b); r[i].push_back(c); } while (cin >> m && m) { memset(book, 0, sizeof(book)); n = 1; bfs(m, 0); } return 0; }
O - 胜利大逃亡(续)
分析:
- 总共十把锁,所以每个点都有对应不同开锁情况的装态,在储存开锁情况是需要使用位运算;除了标记数组和普通BFS不一样,其他一样
代码:
#include<iostream> #include<cstring> using namespace std; int n, m, t,book[21][21][1030]; char a[21][21]; int nx[] = { 0,1,0,-1 }; int ny[] = { 1,0,-1,0 }; struct nb { int x; int y; int t; int f; }r[4000]; int main() { int x, y, c; while (scanf("%d%d%d", &n, &m, &t) != EOF) { memset(book, 0, sizeof(book)); c = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) { scanf(" %c", &a[i][j]); if (a[i][j] == '@') { x = i; y = j; } } int head, tail, tx, ty; head = tail = 1; r[tail].x = x; r[tail].y = y; r[tail].t = 0; r[tail].f = 0; book[x][y][r[tail].f] = 1; tail++; while (head < tail) { for (int i = 0; i < 4; i++) { tx = r[head].x + nx[i]; ty = r[head].y + ny[i]; r[tail].t = r[head].t + 1; r[tail].f = r[head].f; r[tail].x = tx; r[tail].y = ty; if (tx < 0 || tx >= n || ty < 0 || ty >= m || book[tx][ty][r[head].f] == 1 || a[tx][ty] == '*' || r[tail].t >= t) continue; if (a[tx][ty] == '^') { c = 1; break; } else if (a[tx][ty] >= 'a' && a[tx][ty] <= 'j') { int s = a[tx][ty] - 'a'; if ((r[tail].f & (1 << s)) == 0) r[tail].f += (1 << s); } else if (a[tx][ty] >= 'A' && a[tx][ty] <= 'J') { int s = a[tx][ty] - 'A'; if ((r[tail].f & (1 << s)) == 0) continue; } book[tx][ty][r[tail].f] = 1; tail++; } head++; if (c == 1) break; } if (c == 1) printf("%d\n", r[tail].t); else printf("-1\n"); } return 0; }
P - Beat
分析:
- 做的题的难度必须要大于等于做的前一题(难度也就是做题的时间)
- 做完一道题后更新当前难度,重复搜索
代码:
#include<iostream> using namespace std; int n, a[20][20], vis[20], ans; void DFS(int s, int q, int d) { if (s > ans) ans = s; vis[q] = 1; for (int i = 0; i < n; i++) { if (!vis[i] && a[q][i] >= d) DFS(s + 1, i, a[q][i]); } vis[q] = 0; } int main() { while (cin>>n) { memset(vis, 0, sizeof(vis)); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> a[i][j]; ans = 1; DFS(1, 0, 0); cout << ans<< endl; } }