算法竞赛入门经典 例题5-2

UVa101

The Blocks Problem

n个带有编号的石块排成一排,根据命令移动石块:

  • move a onto b,将ab之上的所有石块归位,并将a放到b
  • move a over b,将a之上的所有石块归位,并将a放到包含b的那一摞上
  • pile a onto b,将b之上的所有石块归位,并将包含a的一摞放到b
  • pile a over b,将包含a的一摞放到包含b的那一摞上

如果ab相同或者ab在同一摞,则跳过此命令。

显然石块应该使用二维数组存储,麻烦的是如何知道当前状态下石块的位置,这可以通过使用另外的数组记录每个石块当前的位置并在处理命令的过程中维护位置信息即可。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

void MoveOnto(vector<vector<int>> &blocks, vector<int> &position, int a, int b)
{
	int apos = position[a], bpos = position[b], top;
	if (a == b || apos == bpos) return;
	while (!blocks[apos].empty() && ((top = blocks[apos].back()) != a)) {
		blocks[apos].pop_back();
		blocks[top].push_back(top);
		position[top] = top;
	}
	while (!blocks[bpos].empty() && ((top = blocks[bpos].back()) != b)) {
		blocks[bpos].pop_back();
		blocks[top].push_back(top);
		position[top] = top;
	}
	blocks[bpos].push_back(a);
	blocks[apos].pop_back();
	position[a] = bpos;
}

void MoveOver(vector<vector<int>> &blocks, vector<int> &position, int a, int b)
{
	int apos = position[a], bpos = position[b], top;
	if (a == b || apos == bpos) return;
	while (!blocks[apos].empty() && ((top = blocks[apos].back()) != a)) {
		blocks[apos].pop_back();
		blocks[top].push_back(top);
		position[top] = top;
	}
	blocks[bpos].push_back(a);
	blocks[apos].pop_back();
	position[a] = bpos;
}

void PileOnto(vector<vector<int>> &blocks, vector<int> &position, int a, int b)
{
	int apos = position[a], bpos = position[b], top;
	if (a == b || apos == bpos) return;
	while (!blocks[bpos].empty() && ((top = blocks[bpos].back()) != b)) {
		blocks[bpos].pop_back();
		blocks[top].push_back(top);
		position[top] = top;
	}
	vector<int> tmp;
	while (!blocks[apos].empty() && ((top = blocks[apos].back()) != a)) {
		tmp.push_back(top);
		blocks[apos].pop_back();
	}
	tmp.push_back(a);
	blocks[apos].pop_back();
	while (!tmp.empty()) {
		blocks[bpos].push_back(tmp.back());
		position[tmp.back()] = bpos;
		tmp.pop_back();
	}
}

void PileOver(vector<vector<int>> &blocks, vector<int> &position, int a, int b)
{
	int apos = position[a], bpos = position[b], top;
	if (a == b || apos == bpos) return;
	vector<int> tmp;
	while (!blocks[apos].empty() && ((top = blocks[apos].back()) != a)) {
		tmp.push_back(top);
		blocks[apos].pop_back();
	}
	tmp.push_back(a);
	blocks[apos].pop_back();
	while (!tmp.empty()) {
		blocks[bpos].push_back(tmp.back());
		position[tmp.back()] = bpos;
		tmp.pop_back();
	}
}

int main()
{
	int n = 0;
	cin >> n;
	vector<vector<int>> blocks;
	vector<int> position;
	for (int i = 0; i < n; i++)
	{
		blocks.push_back(vector<int>());
		blocks.back().push_back(i);
		position.push_back(i);
	}
	string command, a, prep, b;
	while (cin >> command) {
		if (command == "quit") break;
		else if (command == "move") {
			cin >> a >> prep >> b;
			if (prep == "onto") {
				MoveOnto(blocks, position, stoi(a), stoi(b));
			}
			else if (prep == "over") {
				MoveOver(blocks, position, stoi(a), stoi(b));
			}
			else;
		}
		else if (command == "pile") {
			cin >> a >> prep >> b;
			if (prep == "onto") {
				PileOnto(blocks, position, stoi(a), stoi(b));
			}
			else if (prep == "over") {
				PileOver(blocks, position, stoi(a), stoi(b));
			}
			else;
		}
		else;
	}
	for (size_t i = 0; i < blocks.size(); i++)
	{
		cout << i << ":";
		for (size_t j = 0; j < blocks[i].size(); j++)
		{
			cout << ' ' << blocks[i][j];
		}
		cout << endl;
	}
	return 0;
}
/*
10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值