谜题(Puzzle, ACM/ICPC World Finals 1993, UVa227)
有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指令:A, B, L, R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“This puzzle has no final configuration.”
例如,图3-5中执行ARRBBL0后,效果如图3-6所示。
输入:
TRGSJ
XDOKI
M VLN
WPABE
UQHCF
ARRBBL0
ABCDE
FGHIJ
KLMNO
PQRS
TUVWX
AAA
LLLL0
ABCDE
FGHIJ
KLMNO
PQRS
TUVWX
AAAAABBRRRLL0
Z
输出:
Puzzle #1:
T R G S J
X O K L I
M D V B N
W P A E
U Q H C F
Puzzle #2:
A B C D
F G H I E
K L M N J
P Q R S O
T U V W X
Puzzle #3:
This puzzle has no final configuration.
#include <iostream>
#include <map>
#include <vector>
#include <cassert>
#include <algorithm>
using namespace std;
const int GSize = 5;
vector<string> grid;
struct Point{
int x,y;
Point(){}
Point(int x,int y):x(x),y(y){}
};
Point operator+(const Point &a, const Point &b){
return Point(a.x+b.x, a.y+b.y);
}
typedef Point Vector;
Point ePos; //空格
map<char, Vector> DIRS;
bool valid(const Point& p){
return (p.x>=0 && p.x<GSize && p.y>=0 && p.y<GSize);
}
void printGrid(){
for(int i=0;i<GSize;i++){
for(int j=0;j<GSize;j++){
if(j) cout<<' ';
cout<<grid[i][j];
}
cout<<endl;
}
}
bool tryMove(char cmd){
if(!DIRS.count(cmd)) return false;
//assert(DIRS.count(cmd));
Point p = ePos + DIRS[cmd];
if(!valid(p)) return false;
swap(grid[p.x][p.y], grid[ePos.x][ePos.y]);
ePos = p;
return true;
}
int main(){
freopen("/Users/zhaohaibo/Desktop/text.txt","r",stdin);
int t=1;
string line;
DIRS['A'] = Vector(-1,0);
DIRS['B'] = Vector(1,0);
DIRS['L'] = Vector(0,-1);
DIRS['R'] = Vector(0,1);
while(true){
grid.clear();
ePos.x = -1;ePos.y = -1;
for(int i=0;i<GSize;i++){
getline(cin, line);
if(line == "Z") return 0;
//assert(line.size() == GSize);
for(int j=0; j<GSize; j++)
if(line[j] == ' '){
//assert(ePos.x == -1 && ePos.y == -1);
ePos.x = i;
ePos.y = j;
}
grid.push_back(line);
}
string moves;
while(true){
getline(cin, line);
//assert(!line.empty());
bool end = (*(line.rbegin()) == '0'); // 判断line的最后一个字符是否为0
if(!end) moves.append(line); // 不是0就全读入moves
else moves.append(line, 0, line.size()-1); // 是0就读入0前面的
if(end) break;
}
bool legal = true;
for(int i=0; i<moves.size(); i++)
if(!tryMove(moves[i])){
legal = false;
break;
}
if(t > 1) cout<<endl;
cout << "Puzzle #" << t++ << ":" << endl;
if(legal) printGrid();
else cout<<"This puzzle has no final configuration."<<endl;
}
return 0;
}