POJ 搜索(3)

搜索

较麻烦的搜索题目训练

poj1069,poj3322,poj1475,poj1924,poj2049,poj3426

广搜的状态优化

poj1768,poj1184,poj1872,poj1324,poj2046,poj1482

深搜的优化

poj3131,poj2870,poj2286

 

 

 

 

 

 

较麻烦的搜索题目训练 

poj 3322

感觉这题应该归类到模拟题。。。bfs&&priority_queue直接模拟就行。昨晚写了一个版本,因为状态记录的太多了,MLE一次。发现总共有三种形状,每种形状可以用一个坐标加一个标号表示。比如约定立着的用(x, y, 0)表示,横着的为(x, y), (x, y + 1)用(x, y, 1)表示,竖着的为(x, y),(x + 1, y)用(x, y, 2)表示。然后直接模拟出每种形状可以转移到的形状,bfs。

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
//#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int inf = ~0u>>2;

using namespace std;

const int maxn = 550;

struct Point {
    int x, y;
    int f;
    Point() {}
    Point(int a, int b, int f) : x(a), y(b), f(f) {}
    bool operator == (const Point p) const {
        return (x == p.x && y == p.y && f == p.f);
    }
};

struct node {
    Point now;
    int dis;
    node() {}
    node(Point a, int b) : now(a), dis(b) {}
    bool operator < (const node& cmp) const {
        return dis > cmp.dis;
    }
};

char mp[maxn][maxn];
bool vis[maxn][maxn][3];
int R, C;
Point s1, s2, tg;

bool inmap(int x, int y) {
    if(x < 0 || x >= R || y < 0 || y >= C)  return false;
    return true;
}

bool check(int x, int y) {
    if(inmap(x, y) && mp[x][y] != '#')  return true;
    return false;
}

priority_queue<node> q;

int bfs() {
    while(!q.empty())   q.pop();
    CL(vis, false);

    q.push(node(s1, 0));
    vis[s1.x][s1.y][s1.f] = true;

    node u;
    int x, y;
    while(!q.empty()) {
        u = q.top(); q.pop();
        //printf("%d %d %d %d\n", u.now.x, u.now.y, u.now.f, u.dis);
        if(u.now == tg) {
            return u.dis;
        }
        x = u.now.x; y = u.now.y;
        if(u.now.f == 0) {
            //u
            if(check(x-2, y) && check(x-1, y) && !vis[x-2][y][2]) {
                vis[x-2][y][2] = true;
                q.push(node(Point(x-2, y, 2), u.dis + 1));
            }
            //d
            if(check(x+1, y) && check(x+2, y) && !vis[x+1][y][2]) {
                vis[x+1][y][2] = true;
                q.push(node(Point(x+1, y, 2), u.dis + 1));
            }
            //l
            if(check(x, y-2) && check(x, y-1) && !vis[x][y-2][1]) {
                vis[x][y-2][1] = true;
                q.push(node(Point(x, y-2, 1), u.dis + 1));
            }
            //r
            if(check(x, y+1) && check(x, y+2) && !vis[x][y+1][1]) {
                vis[x][y+1][1] = true;
                q.push(node(Point(x, y+1, 1), u.dis + 1));
            }
        } else if(u.now.f == 1) {
            //u
            if(check(x-1, y) && check(x-1,y+1) && !vis[x-1][y][1]) {
                vis[x-1][y][1] = true;
                q.push(node(Point(x-1,y,1), u.dis + 1));
            }
            //d
            if(check(x+1,y) && check(x+1,y+1) && !vis[x+1][y][1]) {
                vis[x+1][y][1] = true;
                q.push(node(Point(x + 1, y, 1), u.dis + 1));
            }
            //l
            if(check(x,y-1) && !vis[x][y-1][0] && mp[x][y-1] != 'E') {
                vis[x][y-1][0] = true;
                q.push(node(Point(x, y-1, 0), u.dis + 1));
            }
            //r
            if(check(x, y+2) && !vis[x][y+2][0] && mp[x][y+2] != 'E') {
                vis[x][y+2][0] = true;
                q.push(node(Point(x, y + 2, 0), u.dis + 1));
            }
        } else {
            //u
            if(check(x-1, y) && !vis[x-1][y][0] && mp[x-1][y] != 'E') {
                vis[x-1][y][0] = true;
                q.push(node(Point(x-1, y, 0), u.dis + 1));
            }
            //d
            if(check(x + 2, y) && !vis[x + 2][y][0] && mp[x+2][y] != 'E') {
                vis[x + 2][y][0] = true;
                q.push(node(Point(x+2, y, 0), u.dis + 1));
            }
            //l
            if(check(x, y - 1) && check(x + 1, y - 1) && !vis[x][y - 1][2]) {
                vis[x][y - 1][2] = true;
                q.push(node(Point(x, y - 1, 2), u.dis + 1));
            }
            //r
            if(check(x, y + 1) && check(x + 1, y + 1) && !vis[x][y + 1][2]) {
                vis[x][y+1][2] = true;
                q.push(node(Point(x, y + 1, 2), u.dis + 1));
            }
        }
    }
    return -1;
}

int main() {
    Read();

    int i, j;
    while(~scanf("%d%d", &R, &C)) {
        if(R + C == 0)  break;
        s1 = Point(-1, -1, -1);
        s2 = Point(-1, -1, -1);

        for(i = 0; i < R; ++i) {
            scanf("%s", mp[i]);
            for(j = 0; j < C; ++j) {
                if(mp[i][j] == 'X') {
                    if(s1.x == -1)  s1 = Point(i, j, -1);
                    else    s2 = Point(i, j, -1);
                }
                if(mp[i][j] == 'O') {
                    tg = Point(i, j, 0);
                }
            }
        }
        if(s2.x != -1) {
            if(s1.x == s2.x) {
                s1.y = min(s1.y, s2.y);
                s1.f = 1;
            } else {
                s1.x = min(s1.x, s2.x);
                s1.f = 2;
            }
        } else {
            s1.f = 0;
        }
        int ans = bfs();
        if(ans == -1)   puts("Impossible");
        else    printf("%d\n", ans);
    }
    return 0;
}

 

广搜的状态优化

POJ 1184

这题过的好揪心,这两天忙着复习,3天才过掉。。。

开始直接暴力bfs,然后果断MLE掉,优化一下内存有TLE掉 。后来看题解,有这个ppthttp://wenku.baidu.com/view/0c2742fb770bf78a65295406.html

还有这个解题报告:http://hi.baidu.com/kmzchchycfdeovr/item/6d7358b32be4edf762388eb6

注意,这个解题报告是错误的,不能忽略左移的情况。不如这个数据:000159 000519

思路是对于移动操作和数值变换操作分开处理。

先预处理出移动操作到达某个状态时用到的最小次数。至于这个状态,因为有六个位置,所以可以设定为num[0...5]记录当前和六个位置顺序状态,num[6]记录这六个位置被访问过的状态,num[7]记录到达这个状态的最小步数。被访问过的位置的状态有:

int Psta[10][6] = {
    {1, 0, 0, 0, 0, 0},//0
    {1, 1, 0, 0, 0, 0},//1
    {1, 1, 1, 0, 0, 0},//2
    {1, 1, 1, 1, 0, 0},//3
    {1, 1, 1, 1, 1, 0},//4
    {1, 0, 0, 0, 0, 1},//5
    {1, 1, 0, 0, 0, 1},//6
    {1, 1, 1, 0, 0, 1},//7
    {1, 1, 1, 1, 0, 1},//8
    {1, 1, 1, 1, 1, 1} //9
};

bfs时记录当前六个位置的顺序状态,当前光标的位置,当前被访问过的位置状态(Psta),还有当前用掉的步数。

这个预处理出来每种六个位置顺序状态所用的步数。然后与目标数字进行对比,需要增加或者减少的直接累加上就可以。。。

ps:debug了好久,因为某傻冒错误。。。T_T

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int inf = ~0u>>2;

using namespace std;

struct node {
    int a[6];
    int pos, sta, stp;
};

queue<node> q;

int Psta[10][6] = {
    {1, 0, 0, 0, 0, 0},//0
    {1, 1, 0, 0, 0, 0},//1
    {1, 1, 1, 0, 0, 0},//2
    {1, 1, 1, 1, 0, 0},//3
    {1, 1, 1, 1, 1, 0},//4
    {1, 0, 0, 0, 0, 1},//5
    {1, 1, 0, 0, 0, 1},//6
    {1, 1, 1, 0, 0, 1},//7
    {1, 1, 1, 1, 0, 1},//8
    {1, 1, 1, 1, 1, 1} //9
};

bool vis[10][6][6][6][6][6][6][6];
int num[50000][8], t;

void bfs() {
    while(!q.empty())   q.pop();
    CL(vis, false);
    CL(num, 0);
    t = 0;

    node u, v;
    int i;
    u.pos = 0;
    u.sta = 0;
    u.stp = 0;
    for(i = 0; i < 6; ++i)  u.a[i] = i;
    q.push(u);
    vis[0][0][0][1][2][3][4][5] = true;
    while(!q.empty()) {
        u = q.front(); q.pop();
        for(i = 0; i < 6; ++i) {
            num[t][i] = u.a[i];
        }
        num[t][6] = u.sta;
        num[t++][7] = u.stp;
        v = u;
        ++v.stp;
        if(v.pos > 0) {
            swap(v.a[0], v.a[v.pos]);
            if(!vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]]) {
                vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]] = true;
                q.push(v);
            }
            swap(v.a[0], v.a[v.pos]);
            --v.pos;
            if(!vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]]) {
                vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]] = true;
                q.push(v);
            }
            ++v.pos;
        }
        if(v.pos < 5) {
            ++v.pos;
            if(v.pos > v.sta || (v.sta > 4 && v.pos > v.sta - 5)) {
                if(v.sta == 4 || v.sta == 9)  v.sta = 9;
                else    ++v.sta;
            }
            if(!vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]]) {
                vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]] = true;
                q.push(v);
            }
            v = u; ++v.stp;
            swap(v.a[5], v.a[v.pos]);
            if(v.sta <= 4)  v.sta += 5;
            if(!vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]]) {
                vis[v.sta][v.pos][v.a[0]][v.a[1]][v.a[2]][v.a[3]][v.a[4]][v.a[5]] = true;
                q.push(v);
            }
        }
    }
}

int a[6], b[6];

int main() {
    //freopen("data.in", "r", stdin);
    //freopen("data1.out", "w", stdout);
    bfs();
    int st, ed, i, j;
    while(~scanf("%d%d", &st, &ed)) {
        for(i = 5; i >= 0; --i) {
            a[i] = st%10;
            st /= 10;
        }
        for(i = 5; i >= 0; --i) {
            b[i] = ed%10;
            ed /= 10;
        }
        int ans = inf, stp, p;
        for(i = 0; i < t; ++i) {
            stp = num[i][7];
            /*if(num[i][6] == 9) {
                for(j = 0; j < 6; ++j) {
                    printf("%d", num[i][j]);
                }
                printf(" %d %d\n", num[i][6], num[i][7]);
            }*/
            /*
            for(j = 0; j < 6; ++j) {
                printf("%d", num[i][j]);
            }
            printf(" %d %d\n", num[i][6], num[i][7]);
            */
            for(j = 0; j < 6; ++j) {
                if(a[num[i][j]] != b[j] && !Psta[num[i][6]][j])    break;
                else    stp += abs(a[num[i][j]] - b[j]);
            }
            if(j == 6 && stp < ans)  {ans = stp; p = i;}
        }
        /*
        puts("**************");
        for(j = 0; j < 6; ++j)  printf("%d", a[num[p][j]]);
        puts("\n***************");
        */
        printf("%d\n", ans);
    }
    return 0;
}

 

POJ 1324   

 话说做完这题真想写个贪吃蛇游戏。 

因为蛇的身子很小,只有八个坐标,可以只记录蛇头的位置,然后记录每一个与前一个位置的相对位置关系。只有上下左右,用0, 1, 2, 3表示,这样就可以化成4进制的状态压缩了。直接bfs,注意蛇头走的下一个位置不能碰到蛇身上

时间耗时很大, 写的很烂。。。不知道用A*怎么写。。。

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
//#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int inf = ~0u>>2;

using namespace std;

struct snake {
    int x, y;
    int sta;
    int dis;
    snake() {}
    snake(int a, int b, int c, int d) :
        x(a), y(b), sta(c), dis(d) {}
};

snake st;
queue<snake> q;
bool vis[21][21][16390];
bool mp[21][21];
int n, m, l;
int body[9][2];
int ssta[9];

int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1},};

void get_ssta(int sta) {
    for(int i = 0; i < l-1; ++i) {
        ssta[i] = sta%4;
        sta /= 4;
    }
}

void get_body(snake u) {
    body[l-1][0] = u.x; body[l-1][1] = u.y;
    get_ssta(u.sta);

    for(int i = l - 2; i >= 0; --i) {
        body[i][0] = body[i+1][0] + dir[ssta[i]][0];
        body[i][1] = body[i+1][1] + dir[ssta[i]][1];
    }
}

bool inmap(int x, int y) {
    if(x <= 0 || x > n || y <= 0 || y > m)  return false;
    return true;
}

bool check(int x, int y) {

    if(mp[x][y] == true || !inmap(x, y)) return false;

    for(int i = 0; i < l; ++i) {
        if(x == body[i][0] && y == body[i][1])  return false;
    }
    return true;
}

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

int bfs() {
    while(!q.empty())   q.pop();
    q.push(st);
    snake u;
    CL(vis, false);
    vis[st.x][st.y][st.sta] = true;
    int x, y, i, j, nsta, a, b;

    while(!q.empty()) {
        u = q.front(); q.pop();
        if(u.x == 1 && u.y == 1)    return u.dis;
        get_body(u);
        for(j = 0; j < 4; ++j) {
            x = u.x + dir[j][0];
            y = u.y + dir[j][1];
            if(!check(x, y))    continue;
            nsta = 0;
            a = x; b = y;
            for(i = l - 1; i >= 1; --i) {
                nsta = nsta*4 + pos(a, b, body[i][0], body[i][1]);
                a = body[i][0]; b = body[i][1];
            }
            if(!vis[x][y][nsta]) {
                vis[x][y][nsta] = true;
                q.push(snake(x, y, nsta, u.dis + 1));
            }
        }
    }
    return -1;
}

int main() {
    //Read();

    int i, k, a, b, x, y, cas = 0;
    while(~scanf("%d%d%d", &n, &m, &l)) {
        if(n + m + l == 0)  break;
        CL(vis, false);
        scanf("%d%d", &a, &b);
        st.x = a; st.y = b;
        st.sta = st.dis = 0;
        for(i = 1; i < l; ++i) {
            scanf("%d%d", &x, &y);
            st.sta = st.sta*4 + pos(a, b, x, y);
            a = x; b = y;
        }
        scanf("%d", &k);
        CL(mp, false);
        while(k--) {
            scanf("%d%d", &a, &b);
            mp[a][b] = true;
        }
        printf("Case %d: %d\n", ++cas, bfs());
    }
    return 0;
}

 

 

  

 

 

 

 

 

posted @ 2012-11-26 19:38  AC_Von  阅读(263)  评论(0编辑  收藏  举报