CSU-ACM2017暑期训练7-模拟&&贪心 F

来源:互联网 发布:cg织梦 编辑:程序博客网 时间:2024/05/29 18:25

F - Sokoban

这里写图片描述

Soko-ban is a Japanese word for a warehouse worker, and the name of a classic computer game created in the 1980s. It is a one-player game with the following premise. A single worker is in an enclosed warehouse with one or more boxes. The goal is to move those boxes to a set of target locations, with the number of target locations equalling the number of boxes. The player indicates a direction of motion for the worker using the arrow keys (up, down, left, right), according to the following rules.    If the indicated direction of motion for the worker leads to an empty location (i.e., one that does not have a box or wall), the worker advances by one step in that direction.    If the indicated direction of motion would cause the worker to move into a box, and the location on the other side of the box is empty, then both the worker and the box move one spot in that direction (i.e., the worker pushes the box).    If the indicated direction of motion for a move would cause the worker to move into a wall, or to move into a box that has another box or a wall on its opposite side, then no motion takes place for that keystroke.The goal is to simultaneously have all boxes on the target locations. In that case, the player is successful (and as a formality, all further keystrokes will be ignored). The game has been studied by computer scientists (in fact, one graduate student wrote his entire Ph.D. dissertation about the analysis of sokoban). Unfortunately, it turns out that finding a solution is very difficult in general, as it is both NP-hard and PSPACE-complete. Therefore, your goal will be a simpler task: simulating the progress of a game based upon a player's sequence of keystrokes. For the sake of input and output, we describe the state of a game using the following symbols:Symbol  Meaning.   empty space#   wall+   empty target locationb   boxB   box on a target locationw   workerW   worker on a target locationFor example, the initial configuration diagrammed at the beginning of this problem appears as the first input case below.

Input

Each game begins with a line containing integers R and C, where 4 ≤ R ≤ 15 represents the number of rows, and 4 ≤ C ≤ 15 represents the number of columns. Next will be R lines representing the R rows from top to bottom, with each line having precisely C characters, from left-to-right. Finally, there is a line containing at most 50 characters describing the player's sequence of keystrokes, using the symbols U, D, L, and R respectively for up, down, left, and right. You must read that entire sequence from the input, even though a particular game might end successfully prior to the end of the sequence. The data set ends with the line 0 0.We will guarantee that each game has precisely one worker, an equal number of boxes and locations, at least one initially misplaced box, and an outermost boundary consisting entirely of walls.

Output

For each game, you should first output a line identifying the game number, beginning at 1, and either the word complete or incomplete, designating whether or not the player successfully completed that game. Following that should be a representation of the final board configuration.

Sample Input

8 9##########...#...##..bb.b.##...#w#.##...#b#.##...++++##...#..###########ULRURDDDUULLDDD6 7########..#####.+.+.##.bb#w###....########DLLUDLULUURDRDDLUDRR0 0

Sample Output

Game 1: incomplete##########...#...##..bb...##...#.#.##...#.#.##...+W+B##...#b.###########Game 2: complete########..#####.B.B.##.w.#.###....########

一道简单(坑爹)模拟题,说简单是因为没啥算法,只要照做就行了;说坑爹是因为之前通过“移入、移出目标位置的同时加减目标中箱子的个数,随时判断目标区域的大小和目标中箱子个数”的方法判断是否过关的方法有错,换成了每移动一次就扫面全图,若箱子全在目标中即返回的方式就行了。至于之前的方法错哪了,实在想不到,真坑爹。

#include <cstring>#include <iostream>#include <cstdio>#include <algorithm>#include <vector>//#define TESTusing namespace std;char map[15][16];char keystrokes[51];int R, C, T = 1;int startX, startY, target, inTarget;bool movable(int x, int y, char dir);bool finish();void work();int main(){#ifdef TESTfreopen("test.txt", "r", stdin);#endif // TEST    while(cin >> R >> C){        if(R == 0 && C == 0)            break;        memset(keystrokes, 0, sizeof(keystrokes));        memset(map, 0, sizeof(map));        target = inTarget = 0;        for(int i = 0; i < R; i++)            scanf("%s", map[i]);        scanf("%s", keystrokes);        for(int i = 1; i <= R-1; i++)            for(int j = 1; j <= C-1; j++){                if(map[i][j] == 'W' || map[i][j] == 'w')                   startX = i, startY = j;                //if(map[i][j] == '+' || map[i][j] == 'B'){                //    target++;                //    if(map[i][j] == 'B')                //        inTarget++;                //}            }        work();        if(finish())            printf("Game %d: complete\n", T++);        else            printf("Game %d: incomplete\n", T++);        for(int i = 0; i < R; i++)            printf("%s\n", map[i]);    }    return 0;}void work(){    int x = startX, y = startY;    for(int i = 0; keystrokes[i]!=0; i++){    bool ok;    int vx, vy;        switch (keystrokes[i]){        case 'U':            ok = movable(x,y,'U');            vx = -1; vy = 0;            break;        case 'D':            ok = movable(x,y,'D');            vx = 1; vy = 0;            break;        case 'L':            ok = movable(x,y,'L');            vx = 0; vy = -1;            break;        case 'R':            ok = movable(x,y,'R');            vx = 0; vy = 1;            break;        }        if(ok){            if(map[x][y] == 'W')                map[x][y] = '+';            else                map[x][y] = '.';            if(map[x + vx][y + vy] == '+'){                map[x + vx][y + vy] = 'W';            }            else if(map[x + vx][y + vy] == '.'){                map[x + vx][y + vy] = 'w';            }            if(map[x + vx][y + vy] == 'B'){                map[x + vx][y + vy] = 'W';                if(map[x + 2*vx][y + 2*vy] == '.'){                    map[x + 2*vx][y + 2*vy] = 'b';//                    inTarget--;                }                else if(map[x + 2*vx][y + 2*vy] == '+'){                    map[x + 2*vx][y + 2*vy] = 'B';                }            }            else if(map[x + vx][y + vy] == 'b'){                map[x + vx][y + vy] = 'w';                if(map[x + 2*vx][y + 2*vy] == '.'){                    map[x + 2*vx][y + 2*vy] = 'b';                }                else if(map[x + 2*vx][y + 2*vy] == '+'){                    map[x + 2*vx][y + 2*vy] = 'B';//                    inTarget++;                }            }//cout << keystrokes[i] << endl;//for(int i = 0; i < R; i++)//printf("%s\n", map[i]);//cout << endl;            x += vx; y += vy;//            if(inTarget == target)//                return;            if(finish())                return;        }    }}bool movable(int x, int y, char dir){    int vx, vy;    switch (dir){        case 'U':            vx = -1; vy = 0;            break;        case 'D':            vx = 1; vy = 0;            break;        case 'L':            vx = 0; vy = -1;            break;        case 'R':            vx = 0; vy = 1;            break;    }    if( map[x + vx][y + vy] == '.' ||  map[x + vx][y + vy] == '+'){        return true;    }    if( map[x + vx][y + vy] == 'B' ||  map[x + vx][y + vy] == 'b'){        if(map[x + 2*vx][y + 2*vy] == '.' || map[x + 2*vx][y + 2*vy] == '+')            return true;    }    return false;}bool finish(){    for(int i = 1; i <= R-1; i++)        for(int j = 1; j <= C-1; j++)            if(map[i][j] == 'b')                return false;    return true;}