POJ 1324

贪吃蛇问题,因为图的复杂性,为了空间效率,这时候就要考虑利用状态压缩来处理。

算法倒是没有多复杂,但是非常考验码力,耐心,中间很多细节小错误(循环,判断顺序)

开始状态压缩想的麻烦了,经过思考,将状态压缩集中到贪吃蛇形状,以及利用贪吃蛇的连贯性,就可以大大节省效率

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

typedef long long LL;
const int maxn= 25;
const int maxl= 11;

struct Dox
{
	int hx, hy, bd;
	int v;
	Dox(int _hx= 0, int _hy= 0, int _bd= 0, int _v= 0) : hx(_hx), hy(_hy), bd(_bd), v(_v) {}
};
int n, m, l, k;
int mz[maxn][maxn];
int r[maxl], c[maxl], bd[maxl];
int step[4][2]= {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};
bool vis[maxn][maxn][(1<<14)+5];

void Decode(int code[], int st, const int l)
{
	for (int i= 0; i< l; ++i){
		code[i]= st & 3;
		st>>= 2;
	}
}
int Encode(int code[], const int l)
{
	int st= 0;
	for (int i= l-1; i>= 0; --i){
		st<<= 2;
		st|= code[i];
	}

	return st;
}
int BFS()
{
	if (1== r[1] && 1== c[1]){
		return 0;
	}
	for (int i= 1; i<= n; ++i){
		for (int j= 1; j<= m; ++j){
			memset(vis[i][j], 0, sizeof(vis[i][j]));
		}
	}
	queue<Dox> Q;
	int bd_s= Encode(bd+2, l-1);
	int v= 0;
	Q.push(Dox(r[1], c[1], bd_s, 0));
	vis[r[1]][c[1]][bd_s]= 1;
	Dox cur;

	while (!Q.empty()){
		cur= Q.front();
		Q.pop();
		Decode(bd+2, cur.bd, l-1);
		r[1]= cur.hx;
		c[1]= cur.hy;
		v= cur.v+1;
		for (int i= 2; i<= l; ++i){
			r[i]= r[i-1]+step[bd[i]][0];
			c[i]= c[i-1]+step[bd[i]][1];
		}
		for (int j= l; j> 2; --j){
			bd[j]= bd[j-1];
		}

		for (int i= 0; i< 4; ++i){
			int nx= r[1]+step[i][0], ny= c[1]+step[i][1];
			int flag= 1;
			if (1== nx && 1== ny){
				return v;
			}
			if (nx< 1 || nx> n || ny< 1 || ny> m || mz[nx][ny]){
				continue;
			}
			for (int j= 2; j<= l; ++j){
				if (r[j]== nx && c[j]== ny){
					flag= 0;
					break;
				}
			}
			if (flag){
				bd[2]= 3-i;
				bd_s= Encode(bd+2, l-1);
				if (!vis[nx][ny][bd_s]){
					Q.push(Dox(nx, ny, bd_s, v));
					vis[nx][ny][bd_s]= 1;
				}
			}
		}
	}

	return -1;
}

int main()
{
	int x, y;
	int kase= 0;
	while (~scanf("%d %d %d", &n, &m, &l) && n){
		memset(mz, 0, sizeof(mz));
		for (int i= 1; i<= l; ++i){
			scanf("%d %d", r+i, c+i);
		}
		for (int i= l; i> 1; --i){
			int dr= r[i]-r[i-1], dc= c[i]-c[i-1];
			if (1== dr){
				bd[i]= 0;
			}
			else if (-1== dr){
				bd[i]= 3;
			}
			else if (1== dc){
				bd[i]= 1;
			}
			else if (-1== dc){
				bd[i]= 2;
			}
		}
		scanf("%d", &k);
		for (int i= 0; i< k; ++i){
			scanf("%d %d", &x, &y);
			mz[x][y]= 1;
		}
		printf("Case %d: %d\n", ++kase, BFS());
	}
	return 0;
}
posted @ 2021-04-19 17:14  IdiotNe  阅读(38)  评论(0编辑  收藏  举报