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;
}