一 原题
Don Piele
A square township has been divided up into N2 square plots (1 <= N <= 7). The Farm is located in the upper left plot and the Market is located in the lower left plot. Betsy takes her tour of the township going from Farm to Market by walking through every plot exactly once. Shown below is one possible tour for Betsy when N=3.
---------------- | | | | | F********** | | | | * | ------------*--- | | | * | | ***** | * | | * | * | * | ---*---*----*--- | * | * | * | | M | ****** | | | | | ----------------Write a program that will count how many unique tours Betsy can take in going from Farm to Market for any value of N.
PROGRAM NAME: betsy
INPUT FORMAT
Line 1: A single integer N (1 <= N <= 7)
SAMPLE INPUT (file betsy.in)
3
OUTPUT FORMAT
A single line with a single integer, the number of unique tours.SAMPLE OUTPUT (file betsy.out)
2
二 分析
给定一个n行n列的区域(n<=7),起点在左上角(1,1),终点在左下角(n,1),要求从起点出发,不重复的遍历所有格子。问有多少种不同的路线。
裸搜的话在n=6时就不能秒出了,加上一个简单的剪枝:对每个当前未访问格子记录一下它周边还未访问的邻居数量,任何时候需要保证除了终点外的格子有2个未访问的邻居(一进一出)。对于只剩下2个未访问邻居的点,称之为必经点,如果当前点邻居中有超过1个的必经点,就可以直接返回了,如果只有一个必经点,就走这个方向。
三 代码
运行结果:
USER: Qi Shen [maxkibb3] TASK: betsy LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.000 secs, 4300 KB] Test 2: TEST OK [0.000 secs, 4300 KB] Test 3: TEST OK [0.000 secs, 4300 KB] Test 4: TEST OK [0.000 secs, 4300 KB] Test 5: TEST OK [0.000 secs, 4300 KB] Test 6: TEST OK [0.000 secs, 4300 KB] Test 7: TEST OK [0.490 secs, 4300 KB] All tests OK.
YOUR PROGRAM ('betsy') WORKED FIRST TIME! That's fantastic -- and a rare thing. Please accept these special automated congratulations.
AC代码:
/*
ID:maxkibb3
LANG:C++
PROB:betsy
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 10;
const int dx[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int n, ans, cnt[maxn][maxn];
bool vis[maxn][maxn];
inline bool legal(int x, int y) {
return (x >= 1 && x <= n && y >= 1 && y <= n);
}
inline bool end(int x, int y) {
return (x == n && y == 1);
}
inline bool must(int x, int y) {
return (end(x, y))? (cnt[x][y] == 0): (cnt[x][y] == 1);
}
void dfs(int x, int y, int d) {
if(end(x, y)) {
if(d == n * n) ans++;
return;
}
vis[x][y] = true;
int p = 0, q;
for(int i = 0; i < 4; i++) {
int nx = x + dx[i][0], ny = y + dx[i][1];
if(!legal(nx, ny) || vis[nx][ny]) continue;
cnt[nx][ny]--;
if(must(nx, ny)) {
q = i;
p++;
}
}
if(p == 1) {
dfs(x + dx[q][0], y + dx[q][1], d + 1);
}
else if(p == 0){
for(int i = 0; i < 4; i++) {
int nx = x + dx[i][0], ny = y + dx[i][1];
if(!legal(nx, ny) || vis[nx][ny]) continue;
dfs(nx, ny, d + 1);
}
}
vis[x][y] = false;
for(int i = 0; i < 4; i++) {
int nx = x + dx[i][0], ny = y + dx[i][1];
if(!legal(nx, ny) || vis[nx][ny]) continue;
cnt[nx][ny]++;
}
}
int main() {
freopen("betsy.in", "r", stdin);
freopen("betsy.out", "w", stdout);
cin >> n;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(i == 1 || i == n) {
if(j == 1 || j == n) cnt[i][j] = 2;
else cnt[i][j] = 3;
continue;
}
if(j == 1 || j == n) {
if(i == 1 || i == n) cnt[i][j] = 2;
else cnt[i][j] = 3;
continue;
}
cnt[i][j] = 4;
}
}
dfs(1, 1, 1);
cout << ans << endl;
return 0;
}

本文介绍了Betsy如何从Farm出发,经过每个方格恰好一次,最终到达Market的问题。给出了输入输出格式,并分析了解决该问题的算法,通过在搜索过程中加入剪枝策略,确保在N=6时仍能有效解决。代码实现成功通过了测试,实现了不重复遍历所有格子的路线计数。
2447

被折叠的 条评论
为什么被折叠?



