题意:给出一个贪吃蛇地图,以及贪吃蛇现在身体各个块所在的位置,求它的头走到(1,1)位置最少需要多少步。
分析:搜索题,用vis[20][20][16384]判重,第三维表示蛇的形状,用位操作,每两位表示一个方向(00,01,10,11表示四个方向)。
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
usingnamespace std;
#define maxn 21
#define maxl 9
struct Node
{
int x, y, state, step;
};
struct Point
{
int x, y;
} point[maxl];
bool map[maxn][maxn];
bool vis[maxn][maxn][16384];
bool vis1[maxn][maxn];
int n, m, l;
int maxstep, minstep;
int dir[4][2] =
{
{ -1, 0 },
{ 0, 1 },
{ 1, 0 },
{ 0, -1 } };
void input()
{
for (int i =0; i < l; i++)
scanf("%d%d", &point[i].x, &point[i].y);
int t;
scanf("%d", &t);
memset(map, 0, sizeof(map));
for (int i =0; i < t; i++)
{
int x, y;
scanf("%d%d", &x, &y);
map[x][y] =true;
}
}
bool ok1(Node &a)
{
if (a.x <=0|| a.x > n || a.y <=0|| a.y > m)
returnfalse;
return!vis1[a.x][a.y] &&!map[a.x][a.y];
}
int bfs1()
{
queue<Node> q;
Node temp;
temp.x = point[0].x;
temp.y = point[0].y;
temp.step =0;
q.push(temp);
memset(vis1, 0, sizeof(vis1));
vis1[temp.x][temp.y] =true;
while (!q.empty())
{
temp = q.front();
q.pop();
for (int i =0; i <4; i++)
{
Node temp2;
temp2.x = temp.x + dir[i][0];
temp2.y = temp.y + dir[i][1];
temp2.step = temp.step +1;
if (ok1(temp2))
{
vis1[temp2.x][temp2.y] =true;
if (temp2.x ==1&& temp2.y ==1)
return temp2.step;
q.push(temp2);
}
}
}
return-1;
}
void setmap()
{
for (int i =1; i < l; i++)
map[point[i].x][point[i].y] =true;
}
void clearmap()
{
for (int i =1; i < l; i++)
map[point[i].x][point[i].y] =false;
}
int getmin()
{
return bfs1();
}
int getmax()
{
setmap();
int ret = bfs1();
clearmap();
return ret;
}
int getstate()
{
int ret =0;
for (int i =1; i < l; i++)
{
for (int j =0; j <4; j++)
if (point[i].x == point[i -1].x - dir[j][0] && point[i].y == point[i -1].y - dir[j][1])
{
ret <<=2;
ret |= j;
}
}
return ret;
}
void getpoint(Node &a)
{
int state = a.state;
point[0].x = a.x;
point[0].y = a.y;
for (int i =1; i < l; i++)
{
int d = (state >> ((l - i -1) *2)) &3;
point[i].x = point[i -1].x - dir[d][0];
point[i].y = point[i -1].y - dir[d][1];
}
}
bool ok(Node &a)
{
if (a.x <=0|| a.x > n || a.y <=0|| a.y > m)
returnfalse;
return!vis[a.x][a.y][a.state] &&!map[a.x][a.y];
}
int bfs()
{
queue<Node> q;
int state = getstate();
Node temp;
temp.x = point[0].x;
temp.y = point[0].y;
temp.state = state;
temp.step =0;
q.push(temp);
memset(vis, 0, sizeof(vis));
while (!q.empty())
{
temp = q.front();
q.pop();
getpoint(temp);
setmap();
Node temp2;
for (int i =0; i <4; i++)
{
temp2.x = temp.x + dir[i][0];
temp2.y = temp.y + dir[i][1];
temp2.step = temp.step +1;
temp2.state = (temp.state >>2) | (i << (l -2) *2);
if (ok(temp2))
{
vis[temp2.x][temp2.y][temp2.state] =true;
if (temp2.x ==1&& temp2.y ==1)
{
return temp2.step;
}
q.push(temp2);
}
}
clearmap();
}
return-1;
}
int main()
{
//freopen("t.txt", "r", stdin);
int t =0;
while (scanf("%d%d%d", &n, &m, &l), n | m | l)
{
t++;
input();
if (point[0].x ==1&& point[0].y ==1)
{
printf("Case %d: %d\n", t, 0);
continue;
}
int ans1 = getmin();
int ans2 = getmax();
if (ans1 ==-1)
{
printf("Case %d: %d\n", t, -1);
continue;
}
if (ans1 == ans2)
{
printf("Case %d: %d\n", t, ans1);
continue;
}
minstep = ans1;
if (ans2 ==-1)
maxstep =0x3f3f3f3f;
else
maxstep = ans2;
int ans = bfs();
printf("Case %d: %d\n", t, ans);
}
return0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
usingnamespace std;
#define maxn 21
#define maxl 9
struct Node
{
int x, y, state, step;
};
struct Point
{
int x, y;
} point[maxl];
bool map[maxn][maxn];
bool vis[maxn][maxn][16384];
bool vis1[maxn][maxn];
int n, m, l;
int maxstep, minstep;
int dir[4][2] =
{
{ -1, 0 },
{ 0, 1 },
{ 1, 0 },
{ 0, -1 } };
void input()
{
for (int i =0; i < l; i++)
scanf("%d%d", &point[i].x, &point[i].y);
int t;
scanf("%d", &t);
memset(map, 0, sizeof(map));
for (int i =0; i < t; i++)
{
int x, y;
scanf("%d%d", &x, &y);
map[x][y] =true;
}
}
bool ok1(Node &a)
{
if (a.x <=0|| a.x > n || a.y <=0|| a.y > m)
returnfalse;
return!vis1[a.x][a.y] &&!map[a.x][a.y];
}
int bfs1()
{
queue<Node> q;
Node temp;
temp.x = point[0].x;
temp.y = point[0].y;
temp.step =0;
q.push(temp);
memset(vis1, 0, sizeof(vis1));
vis1[temp.x][temp.y] =true;
while (!q.empty())
{
temp = q.front();
q.pop();
for (int i =0; i <4; i++)
{
Node temp2;
temp2.x = temp.x + dir[i][0];
temp2.y = temp.y + dir[i][1];
temp2.step = temp.step +1;
if (ok1(temp2))
{
vis1[temp2.x][temp2.y] =true;
if (temp2.x ==1&& temp2.y ==1)
return temp2.step;
q.push(temp2);
}
}
}
return-1;
}
void setmap()
{
for (int i =1; i < l; i++)
map[point[i].x][point[i].y] =true;
}
void clearmap()
{
for (int i =1; i < l; i++)
map[point[i].x][point[i].y] =false;
}
int getmin()
{
return bfs1();
}
int getmax()
{
setmap();
int ret = bfs1();
clearmap();
return ret;
}
int getstate()
{
int ret =0;
for (int i =1; i < l; i++)
{
for (int j =0; j <4; j++)
if (point[i].x == point[i -1].x - dir[j][0] && point[i].y == point[i -1].y - dir[j][1])
{
ret <<=2;
ret |= j;
}
}
return ret;
}
void getpoint(Node &a)
{
int state = a.state;
point[0].x = a.x;
point[0].y = a.y;
for (int i =1; i < l; i++)
{
int d = (state >> ((l - i -1) *2)) &3;
point[i].x = point[i -1].x - dir[d][0];
point[i].y = point[i -1].y - dir[d][1];
}
}
bool ok(Node &a)
{
if (a.x <=0|| a.x > n || a.y <=0|| a.y > m)
returnfalse;
return!vis[a.x][a.y][a.state] &&!map[a.x][a.y];
}
int bfs()
{
queue<Node> q;
int state = getstate();
Node temp;
temp.x = point[0].x;
temp.y = point[0].y;
temp.state = state;
temp.step =0;
q.push(temp);
memset(vis, 0, sizeof(vis));
while (!q.empty())
{
temp = q.front();
q.pop();
getpoint(temp);
setmap();
Node temp2;
for (int i =0; i <4; i++)
{
temp2.x = temp.x + dir[i][0];
temp2.y = temp.y + dir[i][1];
temp2.step = temp.step +1;
temp2.state = (temp.state >>2) | (i << (l -2) *2);
if (ok(temp2))
{
vis[temp2.x][temp2.y][temp2.state] =true;
if (temp2.x ==1&& temp2.y ==1)
{
return temp2.step;
}
q.push(temp2);
}
}
clearmap();
}
return-1;
}
int main()
{
//freopen("t.txt", "r", stdin);
int t =0;
while (scanf("%d%d%d", &n, &m, &l), n | m | l)
{
t++;
input();
if (point[0].x ==1&& point[0].y ==1)
{
printf("Case %d: %d\n", t, 0);
continue;
}
int ans1 = getmin();
int ans2 = getmax();
if (ans1 ==-1)
{
printf("Case %d: %d\n", t, -1);
continue;
}
if (ans1 == ans2)
{
printf("Case %d: %d\n", t, ans1);
continue;
}
minstep = ans1;
if (ans2 ==-1)
maxstep =0x3f3f3f3f;
else
maxstep = ans2;
int ans = bfs();
printf("Case %d: %d\n", t, ans);
}
return0;
}