谜题 (Puzzle, ACM/ICPC World Finals 1993, UVa227)-移动之美

从编程角度,个人认为移动的实质就是点与点之间连续的位置交换所形成的假象. 

原题摘录:

谜题 (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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值