JakeLin- [蓝桥杯][2016年第七届真题]路径之谜-题解-DFS/回溯法

题目描述

小明冒充X星球的骑士,进入了一个奇怪的城堡。城堡里边什么都没有,只有方形石头铺成的地面。
假设城堡地面是 n x n 个方格。【如上图】所示。按习俗,骑士要从西北角走到东南角。
可以横向或纵向移动,但不能斜着走,也不能跳跃。每走到一个新方格,就要向正北方和正西方各射一箭。
(城堡的西墙和北墙内各有 n 个靶子)
同一个方格只允许经过一次。但不必走完所有的方格。
如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?
有时是可以的,比如图中的例子。
本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)

输入

第一行一个整数N(0<N<20),表示地面有 N x N 个方格
第二行N个整数,空格分开,表示北边的箭靶上的数字(自西向东)
第三行N个整数,空格分开,表示西边的箭靶上的数字(自北向南)

输出

一行若干个整数,表示骑士路径。

为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3....
比如,图1.png中的方块编号为:
0  1  2  3
4  5  6  7
8  9  10 11
12 13 14 15

样例输入

4
2 4 3 4
4 3 3 3

样例输出

0 4 5 1 2 3 7 11 10 9 13 14 15

原题链接:[蓝桥杯][2016年第七届真题]路径之谜 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 25;
int map[maxn][maxn];   //地图
int to_north[maxn],to_west[maxn];  //目标
int north[maxn],west[maxn];  //统计靶子箭数
int vis[maxn][maxn];  //标记是否访问
int dx[]={0,0,1,-1};  //四个方向
int dy[]={1,-1,0,0};
int n;
vector<int> road; //存储路径,相当于递归中的栈
int res[maxn];
void dfs(int x,int y){
    //加速作用,若访问此节点靶子箭数超过目标则无需判断
    if(north[y]+1 > to_north[y] || west[x]+1 > to_west[x]){  
        return;
    }
    north[y]++;
    west[x]++;
    vis[x][y]=1;
    road.push_back(map[x][y]);
    if(x==n-1 && y==n-1){  //到达终点
        int tag = 1;
        for(int i=0;i<n;i++){   //判断靶子是否达到想要的最终状态
            if(north[i]!=to_north[i] || west[i]!=to_west[i]){
                tag=0;
                break;
            }
        }
        if(tag==1){  //符合条件
            for(int i=0;i<road.size();i++){
                cout<<road[i]<<" ";
            }
            return;
        }
    }
    for(int i=0;i<4;i++){   //遍历四个可达(不越界)方向
        int newx = x + dx[i];
        int newy = y + dy[i];
        if(newx>=0 && newx<n && newy>=0 && newy<n && vis[newx][newy]==0){
            dfs(newx,newy);
        }
    }
    //回溯,回到上一个点的状态
    north[y]--;
    west[x]--;
    road.pop_back();
    vis[x][y]=0;    
}
int main(){
    //初始化
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>to_north[i];
    }
    for(int i=0;i<n;i++){
        cin>>to_west[i];
    }
    int cnt=0;
    for(int i=0;i<n;i++){  //傻傻的做法
        for(int j=0;j<n;j++){
            map[i][j]=cnt++;
        }
    }    
    //调用DFS,从(0,0)开始
    dfs(0,0);
    return 0;
}
发布了20 篇原创文章 · 获赞 15 · 访问量 217

猜你喜欢

转载自blog.csdn.net/qq_37414463/article/details/105375385