从编程角度,个人认为移动的实质就是点与点之间连续的位置交换所形成的假象.
原题摘录:
谜题 (Puzzle, ACM/ICPC World Finals 1993, UVa227)
有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指令:A, B, L, R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“This puzzle has no final configuration.”
例如,图3-5中执行ARRBBL0后,效果如图所示。
----------------------------------------------------------------------------------------------------------------------
简单说一下核心的实现部分
tryMove():通过自定义+,得到新的空格要移动到的位置与现在空格所在位置进行交换.然后将新的空格位置赋值给空格变量.
其实代码中灵活运用结构体,向量,还有string类中方法特别是Map的键值对在行使指令时的方便更值得仔细推敲和学习.最后就是自上而下的编码构建方式体现函数思想.
----------------------------------------------------------------------------------------------------------------------
完整代码:(用Map,是为了方便移动时计算新的空格位置)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <assert.h>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
struct Point{
int x,y;
Point(int x=0,int y=0):x(x),y(y) {}
};
typedef Point Vector;
Point operator + (const Point& A,const Point& B)
{
return Point(A.x+B.x,A.y+B.y);
}
using namespace std;
const int GSize=5;
vector<string> grid;
Vector 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<<' ';//行首(0)不需要空格
//cout<<grid[i][j];
cout<<grid[i][j]<<" ";
}
cout<<endl;
}
}
bool tryMove(char cmd)
{
//cout<<"move "<<cmd<<":"<<endl;
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;
//printGrid();
return true;
}
int main(int argc, char** argv)
{
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);
}
//char move;
string moves;
while(true){
getline(cin,line);
assert(!line.empty());
bool end=*(line.rbegin())=='0';
if(!end) moves.append(line);
else moves.append(line,0,line.size()-1);
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;
}