这题很久以前做的,不过当时没AC - -后来发现是count没有放在代码里面(注意有多组测试数据 - -)
DFS注意回溯的话要把访问标记重置。
剪枝代码放在DFS两个地方,一个是访问领接点之前,这是对一个点状态剪枝,另外一个是放在访问领接点的代码里,是对多个状态的比较关系剪枝。
奇偶剪枝:剩余步数和最小步数的奇偶性相同
#include<iostream>
using namespace std;
#define start 1
#define end 0
int map[100][100];
bool DFS(int x, int y, int ex, int ey, int m, int n, int t, int step)//带上状态 当前步数
{
int min = abs(x - ex) + abs(y - ey);
if (x>=m || y>=n|| x <0 || y <0)//出界
return false;
if (x == ex&&y == ey&&step == t)
{
return true;
} //终点情况
if ((t - step) < min || (t - step - min) % 2 != 0)
return false;
if (step >= t)
return false;
if (!map[x + 1][y])
{
map[x + 1][y] = 1; if (DFS(x + 1, y, ex, ey, m, n, t, step + 1)){ return true; } map[x + 1][y] = 0;
}
if (!map[x - 1][y])
{
map[x - 1][y] = 1; if (DFS(x - 1, y, ex, ey, m, n, t, step + 1)) { return true; }map[x - 1][y] = 0;
}
if (!map[x][y + 1])
{
map[x][y + 1] = 1; if (DFS(x, y + 1, ex, ey, m, n, t, step + 1)){ return true; } map[x][y + 1] = 0;
}
if (!map[x][y - 1])
{
map[x][y - 1] = 1; if (DFS(x, y - 1, ex, ey, m, n, t, step + 1)) { return true; } map[x][y - 1] = 0;
}
return false;
}
int main()
{
int m, n, ex, ey, t, count , sx, sy;
char ch;
while (cin >> m >> n >> t, n + m + t)
{
count = 0;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
{
cin >> ch;
if (ch == 'S')
map[i][j] = start, sx = i, sy = j;
if (ch == 'D')
map[i][j] = end, ex = i, ey = j;
if (ch == '.')
map[i][j] = 0;
if (ch == 'X')
map[i][j] = 1, count++;
}
if (n*m - count <=t)
{
cout << "NO"<<endl; continue;//可行性剪枝
}
if (DFS(sx, sy, ex, ey, m, n, t, 0))
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}