USACO Betsy's Tour 解题报告

大神做了这道题: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;  
}


你可能感兴趣的:(USACO Betsy's Tour 解题报告)