[poj1324]状态压缩+BFS

这题昨天开始做的...因为从来没有做过状态压缩.这是第一次接触.关于这个题没什么好说的,但是...好歹是俺迈出的第一步呐(=@__@=)~~~

昨天写了一遍,写了200行,加上调试的中转代码,膨胀到了6K...我去.后来调了一晚上终于发现了程序的一个bug:在去重时,忽略了蛇身的状态,只关联到了蛇头.

改完以后...果断TLE.昨天的代码用的是5进制数,第一内存爆得厉害,第二用vector数组作为返回对象,多重调用时时间消耗太严重.后来改写4进制,在状态转移时

直接用位运算操作加速.但是还是有各种没用过碰到的问题.今天终于调试成功了.虽然刚开始是WA.但是很快意识到在判断是否为终点时忽略了蛇头一开始就

在终点的数据.改完后TLE,感觉queue和vector耗时太严重,但是queue这部分用数组其实不太好,除非用数组循环.否则极容易越界.于是改了vector部分.删掉了

operator=部分的拷贝和return value.加速效果还是不错的,至少让我AC了( ⊙o⊙ )哇....这题可以双向广搜也可以A*但是我都不会...呵呵...

留下我翔一般的代码作个纪念:

41584K/2375MS

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;

static int BIT = 0xffffff;
const int MAX = 25;
const int MAXN = 1<<16;
bool vis[MAX][MAX][MAXN];
bool Map[MAX][MAX];
/*
		00(N)
	11(W)	01(E)
		10(S)
*/
int Move[4][2] = {-1,0, 0,1, 1,0, 0,-1};
struct Point {
	int x, y;
	Point(){}
	Point(int a, int b):x(a), y(b){}
	bool operator==(const Point& B)const {
		return x == B.x && y == B.y;
	}
};
vector<Point> point(MAX);
struct Node:public Point {
	int x, y;
    int status;
    int steps;
    Node(){}
    Node(int a, int b):x(a),y(b){}
    bool operator==(const Node& B)const {
		return x == B.x && y == B.y;
    }
    bool operator==(const Point& B)const {
		return x == B.x && y == B.y;
    }
}now, next, E(1,1);
int n, m, L, K;

vector<Point> V(MAX);
void decode(int x, int y, int status) {
    //printf("decode %d\n", status);
    V[0] = (Point){x,y}; //snake.push_back((Point){x, y});
    for (int i = 1; i < L; ++i) {
		int dir = status&3;
		status >>= 2;
		x += Move[dir][0], y += Move[dir][1];
		//printf("%d,%d\n", x, y);
		V[i] = (Point){x,y}; //snake.push_back((Point){x,y});
    }
    /* **************/
    //for (int i = 0; i < L; ++i) {
        //printf("%d,%d\n", snake[i].x, snake[i].y);
    //}
    //getchar();
    //return snake;
}

int encode(void) {
    int status = 0, x, y, now;
    for (int i = L-1; i > 0; --i) {
        x = point[i].x - point[i-1].x;
        y = point[i].y - point[i-1].y;
		if (!x) {
			now = (y^1) ? 3 : 1;
		} else {
            now = (x^1) ? 0 : 2;
		}
		status <<= 2;
		status |= now;
    }
    //printf("status = %d\n", status);
    return status;
}

void init(void) {
	BIT = 0;
	for (int i = 1; i < L; ++i) {
        BIT <<= 2;
        BIT |= 3;
	}
	//printf("%d\n", BIT);
	memset(vis, false, sizeof(vis));
    now.x = point[0].x, now.y = point[0].y;
    now.steps = 0;
    now.status = encode();
    //printf("init: now = %d,%d,%d\n", now.x, now.y, now.status);
}

/* 判断next是否合法 */
bool judge(void) {
    if (next.x <= 0 || next.y <= 0
			|| next.x > n || next.y > m || !Map[next.x][next.y]) return false;
	//printf("next = %d,%d\n", next.x, next.y);
    for (int i = 0; i < L; ++i) {
        //printf("ex:%d,%d\n", V[i].x, V[i].y);
        if (next == V[i]) return false;
    }
    //getchar();
    return true;
}
int BFS(void) {
	init();
    queue<Node> Q;
    Q.push(now);
    vis[now.x][now.y][now.status] = true;
    while (!Q.empty()) {
        now = Q.front(); Q.pop();
        if (now == E) return now.steps;
        decode(now.x, now.y, now.status);
        //cout << "now = " << now.x << ", " << now.y << ", " << now.status << endl;
        for (int i = 0; i < 4; ++i) {
            /* 对龟头来说,有四个方向可以钻,当然,不能搞到自己身子, */
			/* 所以三个方向 */
            //printf("now = %d,%d,%d\n", now.x, now.y, now.steps);
            next.x = now.x + Move[i][0];
            next.y = now.y + Move[i][1];
            next.steps = now.steps + 1;
            //printf("next = %d,%d,%d\n", next.x, next.y, next.steps);getchar();
            if (!judge()) continue;
            next.status = (now.status<<2)&BIT;
            next.status |= (i+2)%4;
            if (vis[next.x][next.y][next.status]) continue;
            vis[next.x][next.y][next.status] = true;
            next.steps = now.steps + 1;
            //if (next == E) return next.steps;
            //printf("Push%d: %d,%d,%d,%d\n", i, next.x, next.y, next.steps, next.status);
            Q.push(next);
        }
    }
    return -1;
}
int main() {
    static int cas = 0;
    while (~scanf(" %d %d %d", &n, &m, &L) && L) {
        memset(Map, true, sizeof(Map));
        for (int i = 0; i < L; ++i) {
            scanf(" %d %d", &point[i].x, &point[i].y);
        }
        scanf(" %d", &K);
        int x, y;
        for (int i = 0; i < K; ++i) {
            scanf(" %d %d", &x, &y);
            Map[x][y] = false;
        }
        printf("Case %d: %d\n", ++cas, BFS());
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值