刚开始一看数据范围T是50感觉深搜肯定不行, 以为使用广搜的, 后来写到后面发现, 对于刚好在T时间到达门, 这一点没办法做到, 所以只有用深搜高度剪枝了。。。这题考的是奇偶性剪枝, 但是我不会, 准备去学一下, 现在暂时用这几个普通剪枝擦边AC了。这里还有个小技巧,就是对于图的处理, 先把所有点都初始化为'X', 然后能走通的再设置为‘.’,方便处理, 也就省去了标记数组,走过就标记成‘X’, 然后还原标记什么的。。
#include
#include
#include
using namespace std;
const int maxn = 10;
char G[maxn][maxn];
int X, Y, EX, EY, N, M, T, cnt;
char ch;
int dirx[4] = {0, 0, 1, -1};
int diry[4] = {1, -1, 0, 0};
int abs(int x){
return x >= 0 ? x : -x;
}
bool inmap(int x, int y) {
return x<=N&&x>=1&&y<=M&&y>=1;
}
bool dfs(int x, int y, int t) {
if(t > T) return false; //剪枝1 时间剪枝
if(abs(x-EX)+abs(y-EY)+t>T) return false; //剪枝2 曼哈顿距离剪枝
if(x==EX&&y==EY) {
if(t==T) return true;
else return false; //剪枝3 到了目标点,却不可以在T时间刚好到达
}
for(int i = 0; i < 4; i++) {
int tx = x + dirx[i]; //已经不是第一次卡在这里了。。。这里只能局部不能全局!!
int ty = y + diry[i];
if(inmap(tx, ty) && G[tx][ty] == '.') {
G[tx][ty] = 'X';
if(dfs(tx, ty, t+1)) return true;
G[tx][ty] = '.';
}
}
return false;
}
int main() {
while(scanf("%d%d%d", &N, &M, &T)!=EOF && (N||M||T)) {
getchar(); cnt = 0 ;
memset(G, 'X', sizeof(G));
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= M; j++) {
ch = getchar();
if(ch != 'X') {
G[i][j] = '.';
if(ch == 'D') {
EX = i; EY = j;
}
else if(ch == 'S') {
X = i; Y = j;
}
}
if(ch == 'X') cnt++;
}
getchar();
}
G[X][Y] = 'X';
//剪枝4:N*M-cnt>= T+1;
if(N*M-cnt>=T+1 && dfs(X, Y, 0)) printf("YES\n") ;
else printf("NO\n");
}
return 0;
}
没有奇偶性剪枝之前的效果:
现在再来看看使用了奇偶性剪枝后的效果:
相差都快一秒了。。。。
下面上代码:
#include
#include
#include
using namespace std;
const int maxn = 10;
char G[maxn][maxn];
int X, Y, EX, EY, N, M, T, cnt;
char ch;
int dirx[4] = {0, 0, 1, -1};
int diry[4] = {1, -1, 0, 0};
int abs(int x){
return x >= 0 ? x : -x;
}
bool inmap(int x, int y) {
return x<=N&&x>=1&&y<=M&&y>=1;
}
bool dfs(int x, int y, int t) {
if(t > T) return false; //剪枝1 时间剪枝
if(abs(x-EX)+abs(y-EY)+t>T) return false; //剪枝2 曼哈顿距离剪枝
if(x==EX&&y==EY) {
if(t==T) return true;
else return false; //剪枝3 到了目标点,却不可以在T时间刚好到达
}
for(int i = 0; i < 4; i++) {
int tx = x + dirx[i]; //已经不是第一次卡在这里了。。。这里只能局部不能全局!!
int ty = y + diry[i];
if(inmap(tx, ty) && G[tx][ty] == '.') {
G[tx][ty] = 'X';
if(dfs(tx, ty, t+1)) return true;
G[tx][ty] = '.';
}
}
return false;
}
int main() {
while(scanf("%d%d%d", &N, &M, &T)!=EOF && (N||M||T)) {
getchar(); cnt = 0 ;
memset(G, 'X', sizeof(G));
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= M; j++) {
ch = getchar();
if(ch != 'X') {
G[i][j] = '.';
if(ch == 'D') {
EX = i; EY = j;
}
else if(ch == 'S') {
X = i; Y = j;
}
}
if(ch == 'X') cnt++;
}
getchar();
}
G[X][Y] = 'X';
if(((abs(X - EX) + abs(Y - EY) - T)&1)) printf("NO\n"); //剪枝5:奇偶性剪枝
else if(N*M-cnt>=T+1 && dfs(X, Y, 0)) printf("YES\n") ; //剪枝4:N*M-cnt>= T+1;
else printf("NO\n");
}
return 0;
}