【蓝桥杯】试题 历届真题 路径之谜【第七届】【决赛】【A组】

dfs把所有可能的路径全找了,看看哪个符合要求。用northsum记录北边还可射的箭矢和,westsum记录南边还可射的箭矢和,当他们都为0同时处于最后一个格子就说明找到路径了。

最开始我是用两个数组去存放射了的箭矢,然后每次调用递归函数都和输入的箭矢数目比对,但超时了,哪怕最多只遍历20个位置,所以递归函数里能不用循环就不用循环。

过了的代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<math.h>
#include<set>
#include<string>
#include<stack>
using namespace std;
#include<queue>
int northSum = 0;//北边还可射的箭总和
int westSum = 0;//西边还可射的箭总和
vector<int>ans;
//dfs的过程,grid是城堡(0表示没走过,1表示走过),path是已经走过的路径,已走过的路径留下的北边的箭
//west是已走过的路径留下的西边的箭,ti,tj是当前坐标
void backtrack(vector<vector<int> >& grid, vector<int>& path, vector<int>& north, vector<int>& west, int ti, int tj)
{
	if (ti < 0 || ti >= grid.size() || tj < 0 || tj >= grid.size() || grid[ti][tj] == 1 || ans.size() != 0 || north[tj] <= 0 || west[ti] <= 0)
	{
		return;
	}
	//west和north记录走过的路径留下的箭,当小于0的时候已经不可能满足了,用来剪枝
	west[ti]--;
	north[tj]--;
	grid[ti][tj] = 1;
	//走到这里,就在西边箭的总和和北边箭的总和减去1,当他们为0同时在最后一个格子就是找到路径了
	westSum--;
	northSum--;
	path.push_back(ti * grid.size() + tj);//公式计算当前位置的编号
	//找到了路径
	if (ti == grid.size() - 1 && tj == grid.size() - 1 && westSum == 0 && northSum == 0)
	{
		ans = path;
		return;
	}
	//朝四个方向走
	backtrack(grid, path, north, west, ti + 1, tj);
	backtrack(grid, path, north, west, ti - 1, tj);
	backtrack(grid, path, north, west, ti, tj - 1);
	backtrack(grid, path, north, west, ti, tj + 1);
	//回溯过程
	grid[ti][tj] = 0;
	north[tj]++;
	west[ti]++;
	westSum++;
	northSum++;
	path.pop_back();
}
int main()
{
	int n = 0;
	cin >> n;
	vector<vector<int> >grid(n, vector<int>(n, 0));
	vector<int>north(n, 0);
	vector<int>west(n, 0);
	for (int i = 0; i < n; i++)
	{
		cin >> north[i];
		northSum += north[i];
	}
	for (int i = 0; i < n; i++)
	{
		cin >> west[i];
		westSum += west[i];
	}
	vector<int>path;
	backtrack(grid, path, north, west, 0, 0);
	for (int i = 0; i < ans.size(); i++)
	{
		cout << ans[i] << " ";
	}
	return 0;
}

顺便贴一个超时的代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<math.h>
#include<set>
#include<string>
#include<stack>
using namespace std;
#include<queue>

vector<int>north1;
vector<int>west1;
vector<int>ans;
void backtrack(vector<vector<int> >& grid, vector<int>& path, vector<int>& north, vector<int>& west, int ti, int tj)
{
	if (ti < 0 || ti >= grid.size() || tj < 0 || tj >= grid.size() || grid[ti][tj] == 1||ans.size()!=0)
	{
		return;
	}
	west[ti]++;
	north[tj]++;
	grid[ti][tj] = 1;
	path.push_back(ti * grid.size() + tj);
	if (ti == grid.size() - 1 && tj == grid.size() - 1)
	{
		int tmp = 0;
//就是这个循环,超时了
		for (int i = 0; i < grid.size(); i++)
		{
			if (north1[i] == north[i] && west1[i] == west[i])
			{
				tmp++;
			}
			if (north[i] > north1[i] || west[i] > west1[i])
			{
				grid[ti][tj] = 0;
				north[tj]--;
				west[ti]--;
				path.pop_back();
				return;
			}
		}
		if (tmp == grid.size())
		{
			ans = path;
			return;
		}
	}
	backtrack(grid, path, north, west, ti + 1, tj);
	backtrack(grid, path, north, west, ti - 1, tj);
	backtrack(grid, path, north, west, ti, tj - 1);
	backtrack(grid, path, north, west, ti, tj + 1);
	grid[ti][tj] = 0;
	north[tj]--;
	west[ti]--;
	path.pop_back();
}
int main()
{
	int n = 0;
	cin >> n;
	vector<vector<int> >grid(n, vector<int>(n, 0));
	north1.resize(n);
	west1.resize(n);
	vector<int>north(n, 0);
	vector<int>west(n, 0);
	for (int i = 0; i < n; i++)
	{
		cin >> north1[i];
	}
	for (int i = 0; i < n; i++)
	{
		cin >> west1[i];
	}
	vector<int>path;
	backtrack(grid, path, north, west, 0, 0);
	for (int i = 0; i < ans.size(); i++)
	{
		cout << ans[i] << " ";
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值