码迷,mamicode.com
首页 > 其他好文 > 详细

poj1324 Holedox Moving

时间:2017-08-16 21:55:27      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:minimal   技巧   original   进制   center   sleep   std   清空   rom   

Holedox Moving
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 16980   Accepted: 4039

Description

During winter, the most hungry and severe time, Holedox sleeps in its lair. When spring comes, Holedox wakes up, moves to the exit of its lair, comes out, and begins its new life. 
Holedox is a special snake, but its body is not very long. Its lair is like a maze and can be imagined as a rectangle with n*m squares. Each square is either a stone or a vacant place, and only vacant places allow Holedox to move in. Using ordered pair of row and column number of the lair, the square of exit located at (1,1). 

Holedox‘s body, whose length is L, can be represented block by block. And let B1(r1,c1) B2(r2,c2) .. BL(rL,cL) denote its L length body, where Bi is adjacent to Bi+1 in the lair for 1 <= i <=L-1, and B1 is its head, BL is its tail. 

To move in the lair, Holedox chooses an adjacent vacant square of its head, which is neither a stone nor occupied by its body. Then it moves the head into the vacant square, and at the same time, each other block of its body is moved into the square occupied by the corresponding previous block. 

For example, in the Figure 2, at the beginning the body of Holedox can be represented as B1(4,1) B2(4,2) B3(3,2)B4(3,1). During the next step, observing that B1‘(5,1) is the only square that the head can be moved into, Holedox moves its head into B1‘(5,1), then moves B2 into B1, B3 into B2, and B4 into B3. Thus after one step, the body of Holedox locates in B1(5,1)B2(4,1)B3(4,2) B4(3,2) (see the Figure 3). 

Given the map of the lair and the original location of each block of Holedox‘s body, your task is to write a program to tell the minimal number of steps that Holedox has to take to move its head to reach the square of exit (1,1). 
技术分享

Input

The input consists of several test cases. The first line of each case contains three integers n, m (1<=n, m<=20) and L (2<=L<=8), representing the number of rows in the lair, the number of columns in the lair and the body length of Holedox, respectively. The next L lines contain a pair of row and column number each, indicating the original position of each block of Holedox‘s body, from B1(r1,c1) to BL(rL,cL) orderly, where 1<=ri<=n, and 1<=ci<=m,1<=i<=L. The next line contains an integer K, representing the number of squares of stones in the lair. The following K lines contain a pair of row and column number each, indicating the location of each square of stone. Then a blank line follows to separate the cases. 

The input is terminated by a line with three zeros. 

Note: Bi is always adjacent to Bi+1 (1<=i<=L-1) and exit square (1,1) will never be a stone. 

Output

For each test case output one line containing the test case number followed by the minimal number of steps Holedox has to take. "-1" means no solution for that case.

Sample Input

5 6 4
4 1
4 2
3 2
3 1
3
2 3
3 3
3 4

4 4 4
2 3
1 3
1 4
2 4
4

2 1
2 2
3 4
4 2

0 0 0

Sample Output

Case 1: 9
Case 2: -1

Hint

In the above sample case, the head of Holedox can follows (4,1)->(5,1)->(5,2)->(5,3)->(4,3)->(4,2)->(4,1)->(3,1)->(2,1)->(1,1) to reach the square of exit with minimal number of step, which is nine. 

Source

题意:在一个n*m的方格上,有一条长为L的蛇,由L个关节组成,每次蛇头不能碰到身体和石头,求最少多少步到达(1,1)这个位置.
这道题我不大会,参考了一下其他神犇的博客.
分析:如果没有身体这个限制,那么就是一道bfs的题,如果有身体这个限制,我们就要想办法记录下它的每个关节在哪个位置,下一次会往哪里走.
       显然,我们可以用一个结构体记录每个关节的位置,每个关节下一次走的位置就是它的上一个关节原来的位置,这样的话还是有一个问题:bfs需要一个vis数组记录曾经搜索过的状态,在这道题中我们该记录什么呢?头的位置肯定是要记录的,但是每个关节的位置记录不下来,空间会爆掉,那我们可以记录每个关节行走的方向,但是这样处理比较麻烦,于是我们记录每个关节关于它的后一个关节的相对运动方向.但是这样的话似乎要开一个很多维的数组,这样也实在是太麻烦了,于是可以很自然的想到状态压缩,可是我们有4个方向,压成二进制每位表示的不够啊,那么我们就每2位表示一节的方向就好了.
       有一个优化:由于vis数组很大,我们如果每次清空都会花费大量的时间,所以我们不再是赋值为0,1,而是看它是不是等于当前的tot(第tot组数据),这样就相当于是一个bool判断.
       不过这样还是会超时啊(要疯了!),那么就要用到搜索中常用的技巧了--启发式搜索,也就是A*,不过太麻烦了,就没写,以下是裸bfs代码:
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n, m, l,tot = 1,a[50][50];
int vis[21][21][1 << 14],k;
int d[3][3] = {
    -1,1,-1,
    3,-1,2,
    -1,0,-1
};

int dx[4] = { 1,-1,0,0 }, dy[4] = { 0,0,1,-1 };

struct node
{
    int x[10], y[10], cnt;
};

bool check(int x, int y, node u)
{
    for (int i = 2; i <= l; i++)
        if (x == u.x[i] && y == u.y[i])
            return false;
    return true;
}

int bfs(node x)
{
    queue<node> q;
    q.push(x);
    while (!q.empty())
    {
        node u = q.front();
        q.pop();
        if (u.x[1] == 1 && u.y[1] == 1)
            return u.cnt;
        for (int i = 0; i < 4; i++)
        {
            node v;
            int tx = u.x[1] + dx[i], ty = u.y[1] + dy[i];
            if (tx < 1 || tx > n || ty < 1 || ty > m || a[tx][ty])
                continue;
            if (!check(tx, ty, u))
                continue;
            u.x[0] = tx, u.y[0] = ty;
            int zhuangtai = 0;
            for (int j = l; j >= 1; j--)
            {
                v.x[j] = u.x[j - 1];
                v.y[j] = u.y[j - 1];
                if (j != l)
                {
                    int temp = d[v.x[j] - v.x[j + 1] + 1][v.y[j] - v.y[j + 1] + 1];
                    zhuangtai |= (temp << (14 - j * 2));
                }
            }
            if (vis[tx][ty][zhuangtai] == tot)
                continue;
            vis[tx][ty][zhuangtai] = tot;
            v.cnt = u.cnt + 1;
            q.push(v);
        }
    }
    return -1;
}

int main()
{
    while (scanf("%d%d%d", &n, &m, &l) == 3)
    {
        memset(a, 0, sizeof(a));
        int temp = 0,tx,ty;
        node init;
        scanf("%d%d", &init.x[1], &init.y[1]);
        for (int i = 2; i <= l; i++)
        {
            scanf("%d%d", &init.x[i], &init.y[i]);
            tx = init.x[i - 1] - init.x[i] + 1;
            ty = init.y[i - 1] - init.y[i] + 1;
            temp |= (d[tx][ty] << (14 - (i - 1) * 2));
        }
        vis[init.x[1]][init.y[1]][temp] = tot;
        scanf("%d", &k);
        for (int i = 1; i <= k; i++)
        {
            int aa, bb;
            scanf("%d%d", &aa, &bb);
            a[aa][bb] = 1;
        }
        init.cnt = 0;
        printf("Case %d: %d\n", tot++, bfs(init));
    }

    return 0;
}

 

poj1324 Holedox Moving

标签:minimal   技巧   original   进制   center   sleep   std   清空   rom   

原文地址:http://www.cnblogs.com/zbtrs/p/7375749.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!