您的位置:首页 > 其它

搜索 HOJ 1838 Traffic Jam

2014-02-06 11:32 876 查看

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.


 

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();
}
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: