POJ 1324 BFS+状压

题目链接:http://poj.org/problem?id=1324

模拟贪吃蛇行走到(1,1)方块的最短距离,有障碍物。

错了2次,第一次内存超了,把队列改成stl的,第二次是有起点就是终点的数据。

状态压缩思路:记录蛇头坐标,并记录下一个蛇方块是在该方块的哪个方向,0,1,2,3分别对上,下,左,右。

然后就可以bfs了。

/*--------------------------------------------------------
                       Author:log                         
   Created Time:2016年04月15日 星期五 18时33分42秒
--------------------------------------------------------*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <map>

using namespace std;

const int maxn=22;
const int maxl=9;

bool grap[maxn][maxn];
int n,m,L,k;
int a[maxl],b[maxl];
int state[maxl];
bool vis[maxn][maxn][1<<14];
int dx[4]={1,0,-1,0};
int dy[4]={0,-1,0,1};
struct Node{
	int x,y;
	int st;
	int d;
	Node(){x=y=st=d=0;}
	Node(int x,int y,int st,int d):x(x),y(y),st(st),d(d){}
};
queue<Node>q;

bool check(int x,int y,Node u){
	int _x=u.x,_y=u.y;
	int sp=3;
	int tmp;
	for(int i=L-2;i>=0;i--){
		tmp=(((u.st>>(i*2))&sp)+2)%4;
		_x+=dx[tmp];
		_y+=dy[tmp];
//		printf("        %d %d\n",_x,_y);
		if(_x==x&&_y==y)return false;
	}
	return true;
}

int getstate(int i,int s){
	s>>=2;
	i<<=(2*(L-2));
	return s|i;
}

int bfs(){
	if(a[0]==1&&b[0]==1)return 0;
	while(!q.empty())q.pop();
	memset(vis,0,sizeof(vis));
	Node u;
	u.x=a[0];u.y=b[0];
	for(int i=1;i<L;i++){
		u.st<<=2;
		u.st|=state[i];
	}
	q.push(u);
	vis[u.x][u.y][u.st]=true;
	int x,y,st;
	while(!q.empty()){
		u=q.front();q.pop();
//		printf("%d:%d %d %d %d\n",l,u.x,u.y,u.st,u.d);
		for(int i=0;i<4;i++){
			x=u.x+dx[i];
			y=u.y+dy[i];
			st=getstate(i,u.st);
			if(x<=0||x>n||y<=0||y>m||grap[x][y])continue;
			if(!check(x,y,u))continue;
			if(vis[x][y][st])continue;
//			printf("%d %d %d\n",x,y,st);
			if(x==1&&y==1)return u.d+1;
			vis[x][y][st]=true;
			q.push(Node(x,y,st,u.d+1));
		}
	}
	return -1;
}

int main(){
	int head;
	int t=0;
	while(scanf("%d %d %d",&n,&m,&L)==3&&(n||m||L)){
		memset(grap,0,sizeof(grap));
		for(int i=0;i<L;i++){
			scanf("%d %d",&a[i],&b[i]);
			if(i!=0){
				if(a[i]==a[i-1]-1)state[i]=0;
				else if(b[i]==b[i-1]+1)state[i]=1;
				else if(a[i]==a[i-1]+1)state[i]=2;
				else state[i]=3;
			}
		}
		scanf("%d",&k);
		int a,b;
		for(int i=0;i<k;i++){
			scanf("%d %d",&a,&b);
			grap[a][b]=true;
		}
		printf("Case %d: %d\n",++t,bfs());
	}
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值