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

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[N][N][N][N];
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[N][N];

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][N], n, m, sx, sy, ex, ey, vis[N][N][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][N], n, m, l, vis[N][N][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][N], n, m, l, vis[N][N][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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值