改了之后提交,超时了。。。
原来有一些点是一开始就不能到终点的,没必要去搜索
如:我们把地图标记为0 1相间
0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0
从图中不难看出,从0走到0、从1走到1都需要偶数步,从0走到1或从1走到0都需要奇数步
正好是0^0 = 0, 1^1 = 0, 1^0 = 0^1 = 1;
所以一开始就可以找出起点跟终点对应的数是0还是1,根据以上运算退出是要走偶数步还是奇数步,然后与输入的步数比较,不一样则可以直接跳过
没必要再搜索了
代码:
#include<iostream> #include<string> #include<cmath> using namespace std; struct P { int x; int y; }ps,pd; char map[10][10]; int vis[10][10]; int n, m, t; int dis[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 }; bool flag = true; void dfs(int x, int y, int s) { if (x == pd.x && y == pd.y) //如果走到终点则return { if (s == t) //如果到终点,时间刚好一样,则标记已经找到了,后面的没必要搜索了 { flag = false; } return; } //如果已经找到或走到该点时,该点到终点的最小时间加上走过的时间超过t,则没必要走下去 if (!flag || (abs(x - pd.x) + abs(y - pd.y) + s) > t) { return; } for (int i = 0; i < 4; ++i) { int x1 = x + dis[i][0]; int y1 = y + dis[i][1]; if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && map[x1][y1] != 'X') { map[x1][y1] = 'X'; dfs(x1, y1, s + 1); map[x1][y1] = '.'; } } return; } int main() { //做好0 1 0 1这个表,我暂时只想到这样的方法 for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { if (i % 2 == 0) { if (j % 2) { vis[i][j] = 1; } else { vis[i][j] = 0; } } else if (j % 2 == 0) { vis[i][j] = 1; } else { vis[i][j] = 0; } } } while (cin >> n >> m >> t&&n&&m&&t) { flag = true; int w = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { cin >> map[i][j]; if (map[i][j] == 'S') { map[i][j] = 'X'; ps.x = i; ps.y = j; } else if (map[i][j] == 'D') { pd.x = i; pd.y = j; } else if (map[i][j] == 'X') { w++; } } } if ((vis[ps.x][ps.y] ^ vis[pd.x][pd.y])) //如果结果为1,则说明需要奇数步 { if (t % 2 == 0) //如果给出的时间为偶数,则不能到达 { cout << "NO\n"; continue; } } else { if (t % 2) { cout << "NO\n"; continue; } } //如果起点到终点的最短时间大于给出的时间,货值给出的时间加上墙的个数超过地图上格子数量, //都说明不能再t时刻到达 if ((n * m - w <= t) || (abs(ps.x - pd.x) + abs(ps.y - pd.y)) > t) { cout << "NO\n"; continue; } dfs(ps.x, ps.y, 0); cout << (flag ? "NO" : "YES") << endl; } return 0; }
PS:同学提醒,直接算出最短距离是奇数还是偶数就可以了,不用再打那个0 1 0 1的表了
代码:
#include<iostream> #include<string> #include<cmath> using namespace std; struct P { int x; int y; }ps,pd; char map[10][10]; int n, m, t; int dis[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 }; bool flag = true; void dfs(int x, int y, int s) { if (x == pd.x && y == pd.y) //如果走到终点则return { if (s == t) //如果到终点,时间刚好一样,则标记已经找到了,后面的没必要搜索了 { flag = false; } return; } //如果已经找到或走到该点时,该点到终点的最小时间加上走过的时间超过t,则没必要走下去 if (!flag || (abs(x - pd.x) + abs(y - pd.y) + s) > t) { return; } for (int i = 0; i < 4; ++i) { int x1 = x + dis[i][0]; int y1 = y + dis[i][1]; if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && map[x1][y1] != 'X') { map[x1][y1] = 'X'; dfs(x1, y1, s + 1); map[x1][y1] = '.'; } } return; } int main() { while (cin >> n >> m >> t&&n&&m&&t) { flag = true; int w = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { cin >> map[i][j]; if (map[i][j] == 'S') { map[i][j] = 'X'; ps.x = i; ps.y = j; } else if (map[i][j] == 'D') { pd.x = i; pd.y = j; } else if (map[i][j] == 'X') { w++; } } } if ((abs(ps.x - pd.x) + abs(ps.y - pd.y)) % 2 == 0) //如果最短距离为偶数 { if (t % 2) //如果给出的时间为奇数数,则不能到达 { cout << "NO\n"; continue; } } else { if (t % 2 == 0) { cout << "NO\n"; continue; } } //如果起点到终点的最短时间大于给出的时间,货值给出的时间加上墙的个数超过地图上格子数量, //都说明不能再t时刻到达 if ((n * m - w <= t) || (abs(ps.x - pd.x) + abs(ps.y - pd.y)) > t) { cout << "NO\n"; continue; } dfs(ps.x, ps.y, 0); cout << (flag ? "NO" : "YES") << endl; } return 0; }