搜索 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 |
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.
![](http://acm.hit.edu.cn/hoj/static/img/pic/1838_a.gif)
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(); } }
相关文章推荐
- 搜索 HOJ 1114 Frame Stacking
- 搜索 HOJ 1394 Shortcut
- (简单)搜索 HOJ 1692 Choose Your Own Adventure
- 搜索 HOJ 1868 八数码
- 搜索 HOJ 1357 Calling Extraterrestrial Intelligence Again
- 搜索 HOJ 1749 Doggone Moles
- 搜索(bfs) HOJ 1448 Dungeon Master
- (简单)搜索 HOJ 1022 Spacecraft Malfunction
- 搜索(水) HOJ 1870 Race
- 搜索 HOJ 1320 Square Destroyer
- (简单)搜索 HOJ 1030 Labyrinth
- HOJ 1440 Knight Moves -------简单搜索 BFS 求l两点之间最小的到达步数
- 字符串搜索。HOJ1530 Compound Words。
- 搜索 HOJ 1281 Lagrange's Four-Square Theorem
- (简单) 搜索 HOJ 1044 Transportation
- 搜索(DLX):HOJ 1017 - Exact cover
- hdu 4158 hoj 2581 Go 简单搜索
- 搜索 HOJ 1273 Peg Game
- (简单) 搜索 HOJ 1048 Cipher
- 搜索 HOJ 1226 Lord of the Ring