usaco6.5.3 Betsy's Tour

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 原题

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值