POJ3009

冰块的滑行。

看到此题目求最短路径,想到了广搜算法,开一个结构体记录每一个球所在的位置和墙的状态。

采用广搜+Hash判重。试着写了一下。交上去,结果TLE了。本来也是看POJ上题目分类是深搜的,但给我直观印象求最短路还是采用BFS+Hash的方式。

晒一下我的代码和思路:模拟每一次移动,上下左右

#include<iostream>
#include<cstring>
using namespace std;
const int Arsize=5000;
const int HashTable=1123;
struct Node{
	int x,y;
	int Maps[22][22];
	int dist;
};
Node location[Arsize];
int endx,endy,have_find,width,height;
int head[HashTable],Next[Arsize];
int Hash(int rear){
	int i,j,v;
	for(i=1,v=0;i<=width;i++){
		for(j=1;j<=height;j++){
			v=(v<<1)+location[rear].Maps[i][j];
		}
	}
	return v%HashTable;
}
int try_to_insert(int rear){
	int h=Hash(rear);
	int u=head[h];
	while(u){
		if(memcmp(location[u].Maps,location[rear].Maps,sizeof(location[rear].Maps))==0&&location[u].x==location[rear].x&&location[u].y==location[rear].y)
			return 0;
		u=Next[u];
	}
	Next[rear]=head[h];
	head[h]=rear;
	return 1;
}


int bfs(void){
	int front,rear,i,move,move_ok,nowx,nowy;
	front=1;
	rear=2;
	while(front<rear){
		Node & now=location[front];
		if(location[front].dist>10){
			return 0;
		}
		if(location[front].x==endx&&location[front].y==endy){
			have_find=1;
			return front;
		}
		for(i=1;i<=4;i++){
			nowx=now.x;
			nowy=now.y;
			move_ok=0;
			if(i==1){
				if(now.Maps[nowx-1][nowy]==1)
					continue;
				for(move=nowx-1;move>0;move--){
					if(now.Maps[move][nowy]==1||now.Maps[move][nowy]==3){
						move_ok=1;
						break;
					}
				}
				if(move_ok){
					memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
					location[rear].Maps[move][nowy]=0;
					location[rear].dist=now.dist+1;
					location[rear].y=nowy;
					if(now.Maps[move][nowy]==3)
						location[rear].x=move;
					else
						location[rear].x=move+1;
					if(try_to_insert(rear))
						rear++;
				}
			}
			else if(i==2){
				if(now.Maps[nowx+1][nowy]==1)
					continue;
				for(move=nowx+1;move<=height;move++){
					if(now.Maps[move][nowy]==1||now.Maps[move][nowy]==3){
						move_ok=1;
						break;
					}
				}
				if(move_ok){
					memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
					location[rear].Maps[move][nowy]=0;
					location[rear].dist=now.dist+1;
					location[rear].y=nowy;
					if(now.Maps[move][nowy]==3)
						location[rear].x=move;
					else
						location[rear].x=move-1;
					if(try_to_insert(rear))
						rear++;	
				}
			}
			else if(i==3){
				if(now.Maps[nowx][nowy-1]==1)
					continue;
				for(move=nowy-1;move>0;move--){
					if(now.Maps[nowx][move]==1||now.Maps[nowx][move]==3){
						move_ok=1;
						break;
					}
				}
				if(move_ok){
					memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
					location[rear].Maps[nowx][move]=0;
					location[rear].dist=now.dist+1;
					location[rear].x=nowx;
					if(now.Maps[nowx][move]==3)
						location[rear].y=move;
					else
						location[rear].y=move+1;
					if(try_to_insert(rear))
						rear++;
				}
			}
			else{
				if(now.Maps[nowx][nowy+1]==1)
					continue;
				for(move=nowy+1;move<=width;move++){
					if(now.Maps[nowx][move]==1||now.Maps[nowx][move]==3){
						move_ok=1;
						break;
					}
				}
				if(move_ok){
					memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
					location[rear].Maps[nowx][move]=0;
					location[rear].dist=now.dist+1;
					location[rear].x=nowx;
					if(now.Maps[nowx][move]==3)
						location[rear].y=move;
					else
						location[rear].y=move-1;
					if(try_to_insert(rear))
						rear++;
				}
			}
		}
		front++;
	}
	return 0;
}
int main()
{
	int i,j,front;
	while(cin >> width >> height){
		if(!height&&!width)
			break;
		memset(location,0,sizeof(location));
		memset(head,0,sizeof(head));
		have_find=0;
		for(i=1;i<=height;i++){
			for(j=1;j<=width;j++){
				cin >> location[1].Maps[i][j];
				if(location[1].Maps[i][j]==2){
					location[1].x=i;
					location[1].y=j;
				}
				if(location[1].Maps[i][j]==3){
					endx=i;
					endy=j;
				}
			}
		}
		location[1].dist=0;
		front=bfs();
		if(!have_find)
			cout << "-1\n";
		else{
			cout << location[front].dist << endl;
		}
	}
	return 0;
}

后面又google了一下解题报告,参考了下别人的代码,采用深搜的方式。操作数为深搜的层数,dfs形参中再带两个表示当前球位置的参数,一直搜下去就行了。

照这样写就AC了。

#include<iostream>
#include<cstring>
using namespace std;
int Maps[21][21];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int width,height,endx,endy,startx,starty,minstep;
void dfs(int steps,int nowx,int nowy){
	int i,move_ok,move_x,move_y;
	if(steps>10)
		return ;
	for(i=0;i<4;i++){
		move_ok=0;
		if(Maps[nowx+dx[i]][nowy+dy[i]]==1)
			continue;
		move_x=nowx;
		move_y=nowy;
		while(1){
			move_x=move_x+dx[i];
			move_y=move_y+dy[i];
			if(move_x<=0||move_x>height||move_y<=0||move_y>width)
				break;
			if(Maps[move_x][move_y]==1){
				move_ok=1;
				break;
			}
			if(Maps[move_x][move_y]==3){
				if(minstep>steps){
					minstep=steps;
					break;
				}
			}
		}
		if(move_ok){
			Maps[move_x][move_y]=0;
			dfs(steps+1,move_x-dx[i],move_y-dy[i]);
			Maps[move_x][move_y]=1;
		}
	}
}
int main()
{
	int i,j;
	while(cin >> width >> height){
		if(!width&&!height)
			break;
		memset(Maps,0,sizeof(Maps));
		minstep=11;
		for(i=1;i<=height;i++){
			for(j=1;j<=width;j++){
				cin >> Maps[i][j];
				if(Maps[i][j]==2){
					startx=i;
					starty=j;
				}
			}
		}
		dfs(1,startx,starty);
		if(minstep>10)
			cout << "-1\n";
		else
			cout << minstep << endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值