您的位置:首页 > 其它

poj 1729 Jack and Jill 1376 Robot 1324 Holedox Moving 1475 Pushing Boxes bfs + a*

2015-08-29 20:53 721 查看

poj 1729 Jack and Jill

Jack和Jill要从各自的家走到各自的学校,但是他们俩各自不喜欢对方,因此,需要你找到两个人行走的路线,使得他们路线中两个人最近的直线距离最长。单位时间内,每个人都可以走到相邻的四个格子中。只考虑移动过后两个人所在位置的直线距离。走过的路可以来回走,到达学校之后就不能离开学校了。

其中H,S分别表示Jack的家和学校;h,s分别表示jill的家和学校;*表示两人都不可以走的区域;Jack的家和学校Jill使不能走的,Jill的家和学校Jill也是不能走的。

每个单位时间,Jack和Jill可以从当前位置向相邻的区域走,因为要求走的过程中,两人走的路线距离最近的地方尽可能大,所以每次应该找到队列中点对距离最大的点扩展,所以应该使用优先队列,因为走过的点还可以再走,所以用一个vis[x1][y1][x2][y2]数组来标记当前状态的最优解,也就是说从起点走到这个位置距离最近的时候的最大值。因为还要记录路径,所以把队列中经过的点都存起来,记录上一个点,然后到达结束状态的时候,反着求出来路径。

/*************************************************************************
> File Name: 1729.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2015年08月11日 星期二 15时42分37秒
************************************************************************/

#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())

using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef long long ll;

const double esp = 1e-5;

#define N 35

struct Node;

int n, vis

;
int sx1, sy1, sx2, sy2, ex1, ey1, ex2, ey2, cnt;
int dx[] = {0, -1, 0, 1};
int dy[] = {1, 0, -1, 0};
char direct[] = "ENWS";
char mp

;

int dist(int x1, int y1, int x2, int y2)
{
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
}

struct Node {
int x1, y1, x2, y2, dis, d1, d2, id, pre;
Node() {}
Node(int a, int b, int c, int d, int dd) :x1(a), y1(b), x2(c), y2(d), dis(dd) {}
void output(void)
{
printf("dis = %d\n", dis);
printf("x1 = %d, y1 = %d.\n", x1, y1);
printf("x2 = %d, y2 = %d.\n", x2, y2);
printf("-----------------\n");
}
bool check(void)
{
if (check1() && check2()) {
return true;
} else {
return false;
}
}
bool check1(void)
{
if (x1 == ex1 && y1 == ey1) {
return true;
} else {
return false;
}
}
bool check2(void)
{
if (x2 == ex2 && y2 == ey2) {
return true;
} else {
return false;
}
}
bool operator <(const Node v) const
{
return this->dis < v.dis;
}
}way[1000010];

void bfs(void)
{
priority_queue<Node> q;
clr(vis, -1);
Node v = Node(sx1, sy1, sx2, sy2, dist(sx1, sy1, sx2, sy2));
cnt = 1;
v.d1 = -1;
v.d2 = -1;
v.id = 0;
v.pre = -1;
q.push(v);
way[0] = v;
vis[sx1][sy1][sx2][sy2] = v.dis;
while (!q.empty()) {
Node u = q.top();
q.pop();
//u.output();
if (u.check()) {
printf("%.2f\n", sqrt(1.0 * u.dis));
Node p = u;
string s1, s2;
while (p.pre != -1) {
if (p.d1 != '*') {
s1.pb(p.d1);
}
if (p.d2 != '*') {
s2.pb(p.d2);
}
p = way[p.pre];
}
reverse(s1.begin(), s1.end());
reverse(s2.begin(), s2.end());
cout << s1 << endl;
cout << s2 << endl;
return;
}
for (int i = 0; i < 4; ++i) {
int nx1 = u.x1 + dx[i];
int ny1 = u.y1 + dy[i];
int d1 = direct[i];
if (u.check1()) {
nx1 = u.x1;
ny1 = u.y1;
d1 = '*';
}
if (!mp[nx1][ny1] || mp[nx1][ny1] == '#' || mp[nx1][ny1] == '*') {
;
} else {
for (int j = 0; j < 4; ++j) {
int nx2 = u.x2 + dx[j];
int ny2 = u.y2 + dy[j];
int d2 = direct[j];
if (u.check2()) {
nx2 = u.x2;
ny2 = u.y2;
d2 = '*';
}
if (!mp[nx2][ny2] || mp[nx2][ny2] == '$' || mp[nx2][ny2] == '*') {
;
} else {
int ndis = dist(nx1, ny1, nx2, ny2);
ndis = min(ndis, u.dis);
int vv = vis[nx1][ny1][nx2][ny2];
if (vv == -1 || ndis > vis[nx1][ny1][nx2][ny2]) {
vis[nx1][ny1][nx2][ny2] = ndis;
v = Node(nx1, ny1, nx2, ny2, ndis);
v.d1 = d1;
v.d2 = d2;
v.pre = u.id;
v.id = cnt;
q.push(v);
way[cnt++] = v;
}
}
}
}
}
}
return;
}

int main(int argc, char *argv[])
{
while (scanf("%d", &n) != EOF) {
if (!n) {
break;
}
clr(mp, 0);
for (int i = 1; i <= n; ++i) {
scanf("%s", mp[i] + 1);
for (int j = 1; j <= n; ++j) {
if (mp[i][j] == 'H') {
sx1 = i;
sy1 = j;
mp[i][j] = '$';
} else if (mp[i][j] == 'S') {
ex1 = i;
ey1 = j;
mp[i][j] = '$';
} else if (mp[i][j] == 'h') {
sx2 = i;
sy2 = j;
mp[i][j] = '#';
} else if (mp[i][j] == 's') {
ex2 = i;
ey2 = j;
mp[i][j] = '#';
}
}
}
bfs();
}
return 0;
}


poj 1376 Robot

机器人想要从一个地点到另一个地点,机器人是有直径的,而且机器人只能在格子的交点上移动,但是格子里可能是一些障碍物,因为机器人有直径,所以,在障碍物的周围,机器人是走不到的,也就是说,障碍物阻碍的范围变大了,可以读入障碍物位置的时候将其障碍住的交点弄上标记,但是不要读完之后再去标记,因为这不能确定这里本身是一个障碍物还是障碍物扩展来的。也可以读入的时候不判断,而在扩展的时候动态的判断。因为数据比较小,没有用A*也可以过。

/*************************************************************************
> File Name: 1376.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2015年08月14日 星期五 20时01分24秒
************************************************************************/

#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())

using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef long long ll;

const double esp = 1e-5;

#define N 55

int mp

, n, m, sx, sy, ex, ey, vis

[4], sd;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
char type[100];

struct Node {
int x, y, s, d, pre, id;

Node() {}
Node(int xx, int yy, int ss, int dd): x(xx), y(yy), s(ss), d(dd) {}
bool check(void)
{
if (x == ex && y == ey) {
return true;
} else {
return false;
}
}
void output(void)
{
printf("x = %d, y = %d, s = %d, d = %d, id = %d, pre = %d\n", x, y, s, d, id, pre);
}
};

bool check(int x, int y)
{
if (x <= 0 || y <= 0 || x >= n || y >= m) {
return false;
}
if (mp[x][y] || mp[x - 1][y - 1] || mp[x - 1][y] || mp[x][y - 1]) {
return false;
}
return true;
}

int bfs(void)
{
queue<Node> q;
clr(vis, 0);
Node u = Node(sx, sy, 0, sd);
u.pre = -1;
u.id = 0;
q.push(u);
vis[sx][sy][sd] = 1;
int cnt = 0;
while (!q.empty()) {
u = q.front();
q.pop();
//u.output();
//getchar();
if (u.check()) {
return u.s;
}
Node v;
int nd = (u.d + 1) % 4;
if (!vis[u.x][u.y][nd]) {
v = Node(u.x, u.y, u.s + 1, nd);
v.pre = u.id;
v.id = cnt++;
q.push(v);
vis[u.x][u.y][nd] = 1;
}
nd = (u.d + 3) % 4;
if (!vis[u.x][u.y][nd]) {
v = Node(u.x, u.y, u.s + 1, nd);
v.pre = u.id;
v.id = cnt++;
q.push(v);
vis[u.x][u.y][nd] = 1;
}
for (int i = 1; i <= 3; ++i) {
int ns = u.s + 1;
int nx = u.x + i * dx[u.d];
int ny = u.y + i * dy[u.d];
bool flag = check(nx, ny);
if (!flag) {
break;
}
//printf("%d %d %d %d...\n", nx, ny, mp[nx][ny], check(nx, ny));
if (!vis[nx][ny][u.d]) {
v = Node(nx, ny, ns, u.d);
v.pre = u.id;
v.id = cnt++;
q.push(v);
vis[nx][ny][u.d] = 1;
}
}
}
return -1;
}

int main(int argc, char *argv[])
{
while (scanf("%d%d", &n, &m) != EOF) {
if (n == 0 && m == 0) {
break;
}
clr(mp, 0);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
scanf("%d", &mp[i][j]);
}
}
scanf("%d%d%d%d%s", &sx, &sy, &ex, &ey, type);
switch (type[0]) {
case 'n':
sd = 0;
break;
case 'e':
sd = 1;
break;
case 's':
sd = 2;
break;
case 'w':
sd = 3;
break;
}
printf("%d\n", bfs());
}
return 0;
}


poj 1324 Holedox Moving

一个蛇需要从当前位置移动到指定的位置,因为蛇身体不好保存,所以,用一个整数压缩一下,具体做法是记录蛇头的位置,身体的其他部分记录前一个到当前的方向,因为只有4个方向,所以就可以用2位表示,因为蛇身体最长为8,那么用蛇头在位置x,y就最多有2<<14个状态,因为蛇头的位置不需要再记录了。

每次扩展的时候判断是不是蛇身体或者障碍物就行了。

可以使用曼哈顿距离作为启发函数。

/*************************************************************************
> File Name: 1324.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2015年08月15日 星期六 21时45分46秒
************************************************************************/

#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())

using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef long long ll;

const double esp = 1e-5;

#define N 25

int mp

, n, m, l, vis

[1 << 14];
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
int bx[10];
int by[10];

int getdir(int x, int y, int a, int b)
{
for (int i = 0; i < 4; ++i) {
if (x + dx[i] == a && y + dy[i] == b) {
return i;
}
}
return -1;
}

struct Node {
int x, y, d, st, h;
Node () {}
Node(int xx, int yy, int dd, int sst): x(xx), y(yy), d(dd), st(sst) {}
void output(void)
{
printf("x = %d, y = %d, d = %d, st = %d, mp[x][y] = %d\n", x, y, d, st, mp[x][y]);
}
bool check(void)
{
if (x == 1 && y == 1) {
return true;
} else {
return false;
}
}
bool isbody(int a, int b)
{
bx[0] = x;
by[0] = y;
//printf("x = %d, y = %d\n", bx[0], by[0]);
for (int i = 1; i < l; ++i) {
int dir = (st >> ((i - 1) * 2)) & 3;
bx[i] = bx[i - 1] + dx[dir];
by[i] = by[i - 1] + dy[dir];
//printf("x = %d, y = %d\n", bx[i], by[i]);
}
//printf("...\n");
for (int i = 0; i < l; ++i) {
if (bx[i] == a && by[i] == b) {
return true;
}
}
return false;
}
};

bool operator <(Node u, Node v)
{
return u.d + u.h > v.d + v.h;
}

int geth(int x, int y)
{
return abs(x - 1) + abs(y - 1);
}

int bfs(void)
{
priority_queue<Node> pq;
Node u;
clr(vis, 0);
u.x = bx[0];
u.y = by[0];
u.st = 0;
for (int i = 1; i < l; ++i) {
int dir = getdir(bx[i - 1], by[i - 1], bx[i], by[i]);
//printf("%d\n", dir);
u.st |= (dir << (2 * (i - 1)));
}
u.isbody(1, 1);
u.d = 0;
vis[u.x][u.y][u.st] = 1;
u.h = geth(u.x, u.y);
pq.push(u);
while (!pq.empty()) {
u = pq.top();
pq.pop();
//u.output();
if (u.check()) {
return u.d;
}
for (int i = 0; i < 4; ++i) {
int nx = u.x + dx[i];
int ny = u.y + dy[i];
int nd = u.d + 1;
int nst = ((u.st << 2) & ((1 << 14) - 1)) | ((i + 2) % 4);
Node v = Node(nx, ny, nd, nst);
if (nx < 1 || nx > n || ny < 1 || ny > m) {
continue;
}
//v.output();
//printf("%d %d %d\n", nx, ny, v.isbody(nx, ny) ? 1 : 0);
//printf("mp[%d][%d] = %d, %s, %d %d\n", nx, ny, mp[nx][ny], v.isbody(nx, ny) ? "yes" : "no", vis[nx][ny][nst], nst);
if (mp[nx][ny] == 0 && !u.isbody(nx, ny) && !vis[nx][ny][nst]) {
//printf("%d %d %d\n", nx, ny, 1);
v.h = geth(nx, ny);
pq.push(v);
vis[nx][ny][nst] = 1;
}
}
}
return -1;
}

int main(int argc, char *argv[])
{
int c = 0;
while (scanf("%d%d%d", &n, &m, &l) != EOF) {
if (!n && !m && !l) {
break;
}
clr(mp, 0);
for (int i = 0; i < l; ++i) {
scanf("%d%d", &bx[i], &by[i]);
}
int k;
scanf("%d", &k);
for (int i = 0; i < k; ++i) {
int nx, ny;
scanf("%d%d", &nx, &ny);
mp[nx][ny] = 1;
}
printf("Case %d: %d\n", ++c, bfs());
}
return 0;
}


poj 1475 Pushing Boxes

类似推箱子的游戏,一个人需要将一个箱子推到指定的地方,要求推箱子的步数最少,如果推箱子步数一样,那么,推箱子的步数和走的步数之和最少,如果还相等那么任何一个都行,要求输出具体方案。

可以用一个4维数组来保存状态,每次判断可不可以推箱子就行了,可以加上启发式函数,启发式函数使用曼哈顿距离,因为要求推箱子的步数最少,所以,按照推箱子的步数排序,如果相同再按照总步数排序。

还有另一种方法是先bfs箱子,然后人在bfs,看能否推箱子到这个位置,速度比前面的方法快。

/*************************************************************************
> File Name: 1324.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2015年08月15日 星期六 21时45分46秒
************************************************************************/

#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())

using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef long long ll;

const double esp = 1e-5;

#define N 25

int mp

, n, m, l, vis

[1 << 14];
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
int bx[10];
int by[10];

int getdir(int x, int y, int a, int b)
{
for (int i = 0; i < 4; ++i) {
if (x + dx[i] == a && y + dy[i] == b) {
return i;
}
}
return -1;
}

struct Node {
int x, y, d, st, h;
Node () {}
Node(int xx, int yy, int dd, int sst): x(xx), y(yy), d(dd), st(sst) {}
void output(void)
{
printf("x = %d, y = %d, d = %d, st = %d, mp[x][y] = %d\n", x, y, d, st, mp[x][y]);
}
bool check(void)
{
if (x == 1 && y == 1) {
return true;
} else {
return false;
}
}
bool isbody(int a, int b)
{
bx[0] = x;
by[0] = y;
//printf("x = %d, y = %d\n", bx[0], by[0]);
for (int i = 1; i < l; ++i) {
int dir = (st >> ((i - 1) * 2)) & 3;
bx[i] = bx[i - 1] + dx[dir];
by[i] = by[i - 1] + dy[dir];
//printf("x = %d, y = %d\n", bx[i], by[i]);
}
//printf("...\n");
for (int i = 0; i < l; ++i) {
if (bx[i] == a && by[i] == b) {
return true;
}
}
return false;
}
};

bool operator <(Node u, Node v)
{
return u.d + u.h > v.d + v.h;
}

int geth(int x, int y)
{
return abs(x - 1) + abs(y - 1);
}

int bfs(void)
{
priority_queue<Node> pq;
Node u;
clr(vis, 0);
u.x = bx[0];
u.y = by[0];
u.st = 0;
for (int i = 1; i < l; ++i) {
int dir = getdir(bx[i - 1], by[i - 1], bx[i], by[i]);
//printf("%d\n", dir);
u.st |= (dir << (2 * (i - 1)));
}
u.isbody(1, 1);
u.d = 0;
vis[u.x][u.y][u.st] = 1;
u.h = geth(u.x, u.y);
pq.push(u);
while (!pq.empty()) {
u = pq.top();
pq.pop();
//u.output();
if (u.check()) {
return u.d;
}
for (int i = 0; i < 4; ++i) {
int nx = u.x + dx[i];
int ny = u.y + dy[i];
int nd = u.d + 1;
int nst = ((u.st << 2) & ((1 << 14) - 1)) | ((i + 2) % 4);
Node v = Node(nx, ny, nd, nst);
if (nx < 1 || nx > n || ny < 1 || ny > m) {
continue;
}
//v.output();
//printf("%d %d %d\n", nx, ny, v.isbody(nx, ny) ? 1 : 0);
//printf("mp[%d][%d] = %d, %s, %d %d\n", nx, ny, mp[nx][ny], v.isbody(nx, ny) ? "yes" : "no", vis[nx][ny][nst], nst);
if (mp[nx][ny] == 0 && !u.isbody(nx, ny) && !vis[nx][ny][nst]) {
//printf("%d %d %d\n", nx, ny, 1);
v.h = geth(nx, ny);
pq.push(v);
vis[nx][ny][nst] = 1;
}
}
}
return -1;
}

int main(int argc, char *argv[])
{
int c = 0;
while (scanf("%d%d%d", &n, &m, &l) != EOF) {
if (!n && !m && !l) {
break;
}
clr(mp, 0);
for (int i = 0; i < l; ++i) {
scanf("%d%d", &bx[i], &by[i]);
}
int k;
scanf("%d", &k);
for (int i = 0; i < k; ++i) {
int nx, ny;
scanf("%d%d", &nx, &ny);
mp[nx][ny] = 1;
}
printf("Case %d: %d\n", ++c, bfs());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: