搜索 HOJ 1838 Traffic Jam

Traffic Jam

My Tags   (Edit)

 

  Source : CTU Open 2003
  Time limit : 5 sec   Memory limit : 32 M

Submitted : 14, Accepted : 13

 

Traffic jam is a real nightmare of all drivers. Nobody likes to be stuck in the overfilled streets, when the cars move very slowly, if they even move at all. Professional drivers face traffic jams quite often. Truck drivers of ACM are not an exception. Can you help drivers to find the way out of the traffic jam?

We can model a small (but complicated) traffic jam on a 6 × 6grid of squares. Vehicles (cars and trucks) are scattered over the grid at integer locations, as shown below. Both types of vehicles are 1 square wide. Cars are 2 squares long, and trucks are 3 squares long. Vehicles may be oriented either horizontally (East-West) or vertically (North-South) relative to the grid.

搜索 HOJ 1838 Traffic Jam - 恶魔仁 - 恶魔仁 

Vehicles cannot move through each other, cannot turn, and cannot move over the edge of the grid. They can move in their direction (horizontally-oriented vehicles cannot move vertically and vice versa), as long as they are not blocked by another vehicle or by the edge of the grid. Only one vehicle may move in a single step, but it may move by as many squares at a time as possible, providing there is enough empty space.

Our goal is to move vehicles back and forth until a particular horizontally-oriented vehicle (your own car -- the black one on the picture above) leaves the rightmost (eastern-most) edge of the grid, where it is considered to have escaped the traffic jam. You are to write a program that will find a solution requiring the minimum possible number of moves.

Input

The input file will consist of one or more input scenarios. Each scenario begins with a single integer n, 1 ≤ n ≤ 10, giving the number of vehicles in the scenario. Then there will be 6 lines of input, each containing 6 characters. Each character is either a dot (".) representing an empty square, or a lowercase letter representing a vehicle. Your own vehicle is always oriented horizontally and represented by "x characters. The other vehicles use the letters sequentially, beginning with "a.

The last scenario will be followed by a line containing a single zero.

Output

For each scenario, output a single line with the statement "Scenario #K requires X moves., where K is the number of the scenario (starting with 1) and X is the minimum number of moves required to escape the the traffic jam with the particular car.

If it is not possible to escape, output the sentence "You are trapped in scenario #K. instead.

Sample Input

8
aa...b
c..d.b
cxxd.b
c..d..
e...ff
e.ggg.
8
abbc..
a..c..
axxc..
..gddd
..g..e
..fffe
0
Sample Output
Scenario #1 requires 8 moves.
Scenario #2 requires 25 moves.

 

 

题意:类似华容道把,每个方块只能沿着它的方向移动,目的是把黑色的方块从右边移出

思路:我用的宽搜。这道题目写起来挺麻烦的。因为要用hash判重,我的是开链式的。状态可以考虑用一个long long来表示,因为我们只需要知道每一辆车的头位置,就得到当前的状态了,一辆车的位置我们只需要6位,那么10辆车,最多就60位,够了。然后判相等的时候直接位运算,会快一点。但是我没有用这个方法,因为写到一半才想到,不想改了。状态写出来了,hash写出来了,就是搜索就行了。
 

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

#define MOD 89991  //自己根据需要改大小
#define LL long long
int Move[2][4] = { { 0,1,0,-1},{1,0,-1,0} };
int n , Cas;
char maze[7][7];
bool b[26];

inline bool inRange(int r,int c)
{
        return 0 <= r && r < 6 && 0 <= c && c < 6;
}

struct Car
{
        int r , c;
        int dir , len;
};

struct State
{
        bool vis[6][6];
        Car car[10];
        State * next;
        int step;
}vis[MOD] , *first[MOD] , start;
int sz;


int hashcode(const State & s)
{
        LL ret = 0;
        for (int i = 0 ; i < n ; ++i)
        {
                ret += 1313L*((LL)s.car[i].r*131313^s.car[i].c*13131313)<<2;
                ret %= MOD;
        }
        return ret;
}

bool equals(const State & s1 , const State & s2)
{
        for (int i = 0 ; i < n ; ++i) 
        {
                if (s1.car[i].r!=s2.car[i].r || s1.car[i].c!=s2.car[i].c) return false;
        }
        return true;
}


bool in_vis(const State & s)
{
        int k = hashcode(s);
        State * p = first[k];
        while (p)
        {
                if (equals(s,*p)) return true;
                p = p->next;
        }
        return false;
}

void add(const State & s)
{
        vis[sz] = s;
        int k = hashcode(s);
        vis[sz].next = first[k];
        first[k] = &vis[sz];
        ++sz;
}

void init()
{
        memset(first,0,sizeof(first));
        memset(vis,0,sizeof(vis));
        sz = 0;
}

void input()
{
        for (int i = 0 ; i < 6 ; ++i)
                scanf("%s",maze[i]);
        memset(start.vis,0x3f,sizeof(start.vis));
        memset(b,0,sizeof(b));
        int size = 1;
        start.step = 0;
        for (int i = 0 ; i < 6 ; ++i)
        {
                for (int j = 0 ; j < 6 ; ++j)
                {
                        if (maze[i][j]=='.') continue;
                        start.vis[i][j] = false;
                        if (b[maze[i][j]-'a']) continue;
                        b[maze[i][j]-'a'] = true;
                        int Index = maze[i][j]=='x' ? 0 : size++;
                        Car & veh = start.car[Index];
                        veh.len = 1;
                        veh.r = i , veh.c = j;
                        while (inRange(i,j+veh.len) && maze[i][j]==maze[i][j+veh.len])
                        {
                                start.vis[i][j+veh.len] = false;
                                ++veh.len;
                        }
                        if (veh.len != 1)
                        {
                                veh.dir = 0;
                                continue;
                        }
                        while (inRange(i+veh.len,j) && maze[i][j]==maze[i+veh.len][j])
                        {
                                start.vis[i+veh.len][j] = false;
                                ++veh.len;
                        }
                        veh.dir = 1;
                }
        }
        add(start);
}

bool finish(const State & s)
{
        int dir = s.car[0].dir , len = s.car[0].len , r = s.car[0].r , c = s.car[0].c;
        int i = r+Move[0][dir]*len , j = c+Move[1][dir]*len;
        bool ok = true;
        while (inRange(i,j))
        {
                if (!s.vis[i][j]) 
                {
                        ok = false;
                        break;
                }
                i += Move[0][dir];
                j += Move[1][dir];
        }
        return ok;
}

void solve()
{
        if (start.car[0].dir==1) 
        {
                printf("You are trapped in scenario #%d.\n",Cas);
                return;
        }
        queue<State> q;
        q.push(start);
        while (q.size())
        {
                State tmp = q.front(); q.pop();
                for (int i = 0 ; i < n ; ++i)
                {
                        State now = tmp;
                        ++now.step;
                        int len = now.car[i].len , d = now.car[i].dir;
                        int & r1 = now.car[i].r;
                        int & c1 = now.car[i].c;
                        int r2 = r1+(len-1)*Move[0][d];
                        int c2 = c1+(len-1)*Move[1][d];
                        while (inRange(r2,c2))
                        {
                                r2 += Move[0][d];
                                c2 += Move[1][d];
                                if (!inRange(r2,c2) || !now.vis[r2][c2]) break;
                                now.vis[r1][c1] = true;
                                r1 += Move[0][d];
                                c1 += Move[1][d];
                                now.vis[r2][c2] = false;
                                if (!in_vis(now)) 
                                {
                                        if (i > 0 && finish(now))
                                        {
                                                printf("Scenario #%d requires %d moves.\n",Cas,now.step+1);
                                                return;
                                        }
                                        q.push(now);
                                        add(now);
                                }
                        }
                        now = tmp;
                        r1 = now.car[i].r;
                        c1 = now.car[i].c;
                        r2 = r1+(len-1)*Move[0][d];
                        c2 = c1+(len-1)*Move[1][d];
                        d = (d+2)%4;
                        ++now.step;
                        while (inRange(r1,c1))
                        {
                                r1 += Move[0][d];
                                c1 += Move[1][d];
                                if (!inRange(r1,c1) || !now.vis[r1][c1]) break;
                                now.vis[r1][c1] = false;
                                now.vis[r2][c2] = true;
                                r2 += Move[0][d];
                                c2 += Move[1][d];
                                if (!in_vis(now))
                                {
                                        if (i > 0 && finish(now))
                                        {
                                                printf("Scenario #%d requires %d moves.\n",Cas,now.step+1);
                                                return;
                                        }
                                        q.push(now);
                                        add(now);
                                }
                        }
                }
        }
        printf("You are trapped in scenario #%d.\n",Cas);
}

int main()
{
        while (scanf("%d",&n),n)
        {
                ++Cas;
                init();
                input();
                solve();
        }
}
 


 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值