大神做了这道题:https://www.byvoid.com/blog/usaco-544-betsys-tour。解释得非常清楚,我也是按照这种方法做的,即统计“必经点”的个数,如果为0,则周围点都要试一遍;否则,如果为1,则选择这个必经点走;如果多余1个,则无论选择其中哪个,都会走向死胡同,所以不用再走了。只用这一个优化就可以通过所有测试点,虽然很险。
USER: chen chen [thestor1] TASK: betsy LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.003 secs, 3500 KB] Test 2: TEST OK [0.005 secs, 3500 KB] Test 3: TEST OK [0.005 secs, 3500 KB] Test 4: TEST OK [0.003 secs, 3500 KB] Test 5: TEST OK [0.003 secs, 3500 KB] Test 6: TEST OK [0.011 secs, 3500 KB] Test 7: TEST OK [0.969 secs, 3500 KB] All tests OK.网上和标准答案都是用的这个优化,只不过实现地更有效些,即用一个数组保存每个点周围的没有访问过的点的个数,并实时更新,这样不必每步都重新计算。Your program ('betsy') produced all correct answers! This is your submission #2 for this problem. Congratulations!
大神提到了另外一个优化,就是对那种“一分为二”的情况直接跳出。但我总觉得有点困惑,觉得需要判断整行或整列的情况才能得到,所以没有使用(当然,主要是测试点都过了)。
/* ID: thestor1 LANG: C++ TASK: betsy */ #include <iostream> #include <fstream> #include <cmath> #include <cstdio> #include <cstring> #include <climits> #include <cassert> #include <string> #include <vector> #include <list> #include <set> #include <map> #include <queue> #include <stack> #include <algorithm> #include <cassert> using namespace std; const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1}; // 88418 int cntfree(int r, int c, int N, std::vector<std::vector<bool> > &visited) { int nr, nc; int nfree = 0; for (int d = 0; d < 4; ++d) { nr = r + dx[d], nc = c + dy[d]; if (nr < 0 || nr >= N || nc < 0 || nc >= N || visited[nr][nc]) { continue; } nfree++; } return nfree; } void DFS(int r, int c, int N, std::vector<std::vector<bool> > &visited, int &cnt, int nvisited) { if (r == N - 1 && c == 0) { if (nvisited == N * N) { cnt++; } return; } visited[r][c] = true; int nr, nc; int naccesspoint = 0, accessr, accessc; for (int d = 0; d < 4; ++d) { nr = r + dx[d], nc = c + dy[d]; if (nr < 0 || nr >= N || nc < 0 || nc >= N || visited[nr][nc] || (nr == N - 1 && nc == 0)) { continue; } int nfree = cntfree(nr, nc, N, visited); if (nfree == 1) { naccesspoint++; accessr = nr, accessc = nc; } } // if more than 1 access points, then there will be dead end if (naccesspoint == 0) { for (int d = 0; d < 4; ++d) { nr = r + dx[d], nc = c + dy[d]; if (nr < 0 || nr >= N || nc < 0 || nc >= N || visited[nr][nc]) { continue; } DFS(nr, nc, N, visited, cnt, nvisited + 1); } } else if (naccesspoint == 1) { DFS(accessr, accessc, N, visited, cnt, nvisited + 1); } visited[r][c] = false; } int main() { ifstream fin("betsy.in"); int N; fin >> N; fin.close(); std::vector<std::vector<bool> > visited(N, std::vector<bool>(N, false)); int cnt = 0; DFS(0, 0, N, visited, cnt, 1); ofstream fout("betsy.out"); fout << cnt << endl; fout.close(); return 0; }