这篇分享没有别的目的只是觉得这一题的记忆化搜索的套路比滑雪这道题更好且本人不太会记忆化搜索就写了这篇!!!
第一次提交:
#include<iostream>
using namespace std;
const int N = 110;
char s[N][N];
int r1, c1, r2, c2;
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };
int T;
int ans;
int n, m;
void dfs(int x1,int y1, int t)
{
if (t > T)
{
if (x1 == r2 && y1 == c2) ans++;
return;
}
for (int i = 0; i < 4; i++)
{
int x = x1 + dx[i], y = y1 + dy[i];
if (x <= n && x >= 1 && y1 <= m && y >= 1 && s[x][y] != '*')
{
dfs(x, y, t + 1);
}
}
}
int main()
{
cin >> n >> m >> T;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> s[i][j];
}
}
cin >> r1 >> c1 >> r2 >> c2;
dfs(r1, c1, 1);
cout << ans << '\n';
return 0;
}
在第一次提交时我一直有个疑惑就是到底加不加vis这个数组:即我认为可能会出现重复的现象,不过后面认为vis是只有在点可能会出现重复访问的情况然而这道题点本身就可以重复访问的。第一次只拿了42分。
在第二次题解加了一个剪枝:
if (abs(x1 - r2) + abs(y1 - c2) > T - t + 1) return;
瞬间来到88分,可见剪枝的重要性。同时这个剪枝也是之前做过别的题目知道的也可见刷题重要性。
不过还是2个点超时,为此看了题解知道要用记搜原本我就想这题可能要用记搜不过由于不熟还是没用
下面就是需要记住的记搜的套路(别的记搜应该和这个差不多):
int dfs(int x1,int y1, int t)
{
if (re[x1][y1][t] != -1) return re[x1][y1][t];
if (abs(x1 - r2) + abs(y1 - c2) > T - t + 1) return re[x1][y1][t]=0;
if (t ==T+1)
{
if (x1 == r2 && y1 == c2) return re[x1][y1][t] = 1;
else return re[x1][y1][t] = 0;
}
int ans = 0;
for (int i = 0; i < 4; i++)
{
int x = x1 + dx[i], y = y1 + dy[i];
if (x <= n && x >= 1 && y1 <= m && y >= 1 && s[x][y] != '*')
{
ans += dfs(x, y, t + 1);
}
}
return re[x1][y1][t] = ans;
}
结束....