usaco6.5.3 Betsy's Tour

一 原题

Betsy’s Tour
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;
}

    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/max_kibble/article/details/79367573
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞