前言:
本题使用的是dfs,我个人认为和飞机降落那道题的解法思路相差不大——
http://t.csdnimg.cn/H6CAqhttp://t.csdnimg.cn/H6CAq
一、题目解析
题目的意思就是,从入口到出口,对于小明走过的每一个格子,都会使得这个格子对应的行或者列的靶子上的数数字加一。现在给了我们所有靶子上的数字,让我们推断出小明的路径是什么,题目保证了一定有合法的路径。
下面就来对这个题目所使用的算法做进一步的分析。
二、算法分析
对于这种搜索类的题目而言,常用的方法无非两种,一种是深搜(dfs),另一种是宽搜(bfs),这两种方法无所谓好坏,只是我一般习惯用深搜。但是在处理最短路径的时候就必须要使用宽搜了。
那么我们要怎么做呢?试着考虑一下,我们从起点开始搜索,直到我们搜索到终点结束,在搜索到终点的时候,我们判断一个这个终点的合法性,如果合理的话,我们就返回true,否则我们返回false。
好,现在来逐步实现一下这些步骤和细节点——
首先的输入,输出的问题,比较简单,我们直接写出。
#include <bits/stdc++.h>
using namespace std;
const int N = 25;
int g[N][N],col[N],row[N];
int n;
int main()
{
cin>>n;
for(int i = 0;i<n;i++)scanf("%d",&col[i]);
for(int i = 0;i<n;i++)scanf("%d",*row[i]);
int k = 0;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
g[i][j] = k++;
}
}
return 0;
}
接下来我们来分析dfs的过程。
由于题目要求我们每一个格子只能走一次,所以我们需要记录每一个格子的状态,如果它已经被使用过了,我们就不能在遍历它了,否则可能会出现死循环的情况。
其次就是,如何遍历?我们采取向量的方法,定义了四个方向,从一个点向他的四周扩展,判断其合法性,如果合法的话,就可以继续搜索。(不合法的情况大概有,越界,该点已被搜索,如果走了该点,那么它的行,列对应的数字就会超过题目给我们的数据)
关键的一点来了,就是如何知道在搜索过程中,这个点的行,列对应的数字是多少呢?
我们不妨再开两个数组(r[ ],c[ ])来存储这两个信息。
至于我们的路径,由于它在搜索过程中是不断变化的,我们不妨开一个加长数组vector<int>path,来储存我们的路径。
思路大致就是这样的,如果大家感兴趣的话,希望大家可以先自行书写一下代码,或者也可以看一下我下边的代码,比对,交流一下。
三、代码呈现
#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 25;
vector<int>path;
int row[N],col[N];
int r[N],c[N];
int g[N][N];
bool state[N][N];
int dx[4] = {1,-1,0,0},dy[4] = {0,0,1,-1};
bool dfs(int sx,int sy)
{
if(sx==n-1&&sy==n-1)//递归出口
{
for(int i = 0;i<n;i++)
{
if(r[i]!=row[i]||c[i]!=col[i])return false;
}
return true;
}
for(int i = 0;i<4;i++)//四个方向开始搜索
{
int x = sx+dx[i],y = sy+dy[i];
if(x<0||x>=n||y<0||y>=n||c[y]==col[y]||r[x] == row[x]||state[x][y])continue;
state[x][y] = true;
c[y]++,r[x]++;
path.push_back(g[x][y]);
if(dfs(x,y)) return true;//这里相当于一个剪枝的操作,只要我们找到了一个合法的路径,自然就没有必要继续下去了
path.pop_back();
c[y]--,r[x]--;
state[x][y] = false;//都是回溯的过程,注意不要忘记
}
return false;//如果能执行这个代码,就说明现在走的路径不是一个合法的路径,所以我们直接返回假即可
}
int main()
{
cin>>n;
int k = 0;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
g[i][j] = k++;
}
}
for(int i = 0;i<n;i++)scanf("%d",&col[i]);
for(int i = 0;i<n;i++)scanf("%d",&row[i]);
r[0] = 1,c[0] = 1;
path.push_back(g[0][0]);
state[0][0] = true;
dfs(0,0);
for(int i = 0;i<path.size();i++)cout<<path[i]<<' ';
return 0;
}