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