Tempter of the Bone
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
输入n,m,t
n * m的地图
题意:从s出发,初始时间为0, 只有在第t秒,D会开门,判断能否走出迷宫。
思路:暴搜,没有剪枝预判的话会超时。
剪枝:
假设sx,sy为起点,则ex,ey为终点,任意点
如果
1.abs(sx - ex) + abs(sy - ey) > t
2.abs(sx - ex) + abs(sy - ey) % 2 != t % 2(即到达D的时候时间不同步)
以上任意情况则一定不能走出去了
每次在迷宫移动的时候,同理,对此剪枝。
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<list>
#define mod 998244353
#define INF 0x3f3f3f3f
#define Min 0xc0c0c0c0
#define mst(a) memset(a,0,sizeof(a))
#define f(i,a,b) for(int i = a; i < b; i++)
using namespace std;
typedef long long ll;
const int MAX_N = 1e6 + 5;
int n, m, t;
int sx, sy, ex, ey;
char maps[10][10];
bool vis[10][10];
bool flag;
const int fx[4] = {1, 0, -1, 0};
const int fy[4] = {0, 1, 0, -1};
void dfs(int x, int y, int sum){
if(maps[x][y] == 'D' && sum == t){
flag = true;
return ;
}
if(flag){
return ;
}
for(int i = 0; i < 4; i++){
int nx = x + fx[i], ny = y + fy[i];
int tmp = abs(nx - ex) + abs(ny - ey); //剪枝
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && maps[nx][ny] != 'X' && (sum + tmp + 1 <= t) && (sum + tmp + 1) % 2 == (t % 2) && !vis[nx][ny]){
vis[nx][ny] = 1;
dfs(nx, ny, sum + 1);
vis[nx][ny] = 0;
}
}
}
int main(){
ios::sync_with_stdio(false);
//freopen("c1.txt", "w", stdin);
//freopen("c2.txt", "r", stdout);
int cas = 1;
while(cin>>n>>m>>t){
if(n == 0 && m == 0 && t == 0){
break;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m ;j++){
cin>>maps[i][j];
if(maps[i][j] == 'S'){
sx = i, sy = j;
}
if(maps[i][j] == 'D'){
ex = i, ey = j;
}
}
}
mst(vis);
flag = false;
int tmp = abs(ex - sx) + abs(ey - sy);
if(tmp > t || tmp % 2 != t % 2){ //预判
cout<<"NO"<<endl;
continue;
}
vis[sx][sy] = 1;
dfs(sx, sy, 0);
if(flag){
cout<<"YES"<<endl;
}
else {
cout<<"NO"<<endl;
}
}
//fclose(stdin);
//fclose(stdout);
return 0;
}
另一种方法:
修改'X'的标记,奇偶剪枝不变
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
char maps[10][10];
int sx, sy, ex, ey;
int n, m, t;
bool flag;
bool inbound(int x, int y) { //边界判断 & 墙壁判断
return (x >= 0 && x < n && y >= 0 && y < m && maps[x][y] != 'X');
}
void dfs(int x, int y, int times) {
if (times > t || flag) return;
if (times == t && x == ex && y == ey) {
flag = true;
return;
}
int remain = t - times - (abs(x - ex) + abs(y - ey));
if (remain < 0 || remain & 1) return; //奇偶剪枝
for (int i = 0; i < 4; i++) {
int fx = x + dir[i][1];
int fy = y + dir[i][0];
if (inbound(fx, fy)) {
maps[fx][fy] = 'X';
dfs(fx, fy, times + 1);
maps[fx][fy] = '.'; //回溯
}
}
}
int main() {
while (scanf("%d%d%d", &n, &m, &t) != EOF) {
if (n == 0 && m == 0 && t == 0) break;
flag = false;
for (int i = 0; i < n; i++) {
scanf("%s", maps[i]);
}
int block = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (maps[i][j] == 'S') {
sx = i, sy = j;
}
else if (maps[i][j] == 'D') {
ex = i, ey = j;
}
else if (maps[i][i] == 'X') {
block++;
}
}
}
if (n * m - block <= t) { //剪枝
printf("NO\n");
continue;
}
maps[sx][sy] = 'X';
dfs(sx, sy, 0);
if (flag) {
printf("YES\n");
}
else {
printf("NO\n");
}
}
}