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

来源:互联网 发布:屠龙战记翅膀进阶数据 编辑:程序博客网 时间:2024/06/16 13:03

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 35struct 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 55int 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 25int 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 25int 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
原创粉丝点击