hdoj--1010 ---Tempter of the Bone (dfs + 一些剪枝(擦边AC了), 居然又犯了老毛病, 我没有用奇偶性剪枝)

刚开始一看数据范围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; 
} 


你可能感兴趣的:(hdoj--1010 ---Tempter of the Bone (dfs + 一些剪枝(擦边AC了), 居然又犯了老毛病, 我没有用奇偶性剪枝))