hdu acm 1010

一、奇偶性剪枝

我们把map的奇偶性以01编号:
0 1 0 1 0 1 
1 0 1 0 1 0 
0 1 0 1 0 1 
1 0 1 0 1 0 
0 1 0 1 0 1 
我们发现从0走一步一定走到1,从1走一步一定走到0。
也就是说,如果当前的狗所在的坐标与D的坐标奇偶性不一样,那么狗需要走奇数步。
同理,如果狗所在坐标与D的坐标奇偶性一样,那么狗需要走偶数步数。
 
也就是说,狗的坐标x、y和对2取余是它的奇偶性,Dxy和对2取余是D的奇偶性。
两个奇偶性一加再对2取余,拿这个余数去与剩下时间对2取余的余数作比较即可。

二、距离剪枝

矩阵的大小是N*M 墙的数量记为wall 如果能走的路的数量 N*M - wall 小于时间T,就是说走完也不能到总的时间的,这显然是错误的,可以直接跳出了。


#include <iostream>
#include <math.h>

using namespace std;
	
char maze[7][7];
int n, m, t, i, j;
int sx, sy;
int gx, gy;
	
int d[7][7];

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

int flag, wall;

void dfs(int x, int y, int time) {
	
	if(x == gx & y == gy) {
		if(time == t)
			flag = 1;
			
		return;
	}
	
	//剪枝
	if(time >= t) 
		return;
		
	for(int i=0; i<4; i++) {
		
		int nx = x + dx[i];
		int ny = y + dy[i];
		
		if(nx < n & 0 <= nx & ny < m & 0 <= ny & maze[nx][ny] != 'X') {
			maze[x][y] = 'X';
			dfs(nx, ny, time + 1);
			maze[x][y] = '.';
			//剪枝
			if(flag)
				return;
		}
	}
	 
}

int main() {
	
	while(cin >> n >> m >> t) {

		if(n==0 & m==0 & t==0)
			break;
		
		flag = 0;
		wall = 0;
		for(i=0; i<n; i++) {
			for(j=0; j<m; j++) {
				cin >> maze[i][j];
				if(maze[i][j] == 'S') {
					sx = i;
					sy = j;
				}
				
				if(maze[i][j] == 'D') {
					gx = i;
					gy = j;
				}
				
				if(maze[i][j] == 'X')
					wall ++;
			}
		}
		
		//剪枝
		if(n * m - wall < t) {
			cout << "NO" << endl;
            continue;
		}
			
		//剪枝
		if(abs(sx-gx)+abs(sy-gy)>t||(sx+gx+sy+gy+t)%2==1) {
            cout << "NO" << endl;
            continue;
        }
		
		dfs(sx, sy, 0);
		
		if(flag)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	
	return 0;
} 



posted @ 2016-06-14 16:36  StevenLuke  阅读(172)  评论(0编辑  收藏  举报