UVA - 127 - Accordian patience

传送门:

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18732

题意:

    输入52张扑克牌,进行"Accordian patience"确认。规则如下:

    ① 两张牌匹配条件:数字一样,或花色一样。

    ② 如果当前牌与左边第三位置的牌匹配,则移动当前牌到左边第三位置上方。

    ③ 如果当前牌与左边第一位置的牌匹配,则移动当前牌到左边第一位置上方。

    ④ 优先度:“左边第三张牌”优先于“左边第一张牌”

    ⑤ 每个位置相当一个栈,在顶端的牌才有效用于“比较”和“移动”。

    ⑥ 如果当前位置牌都被移光,则把右边位置的牌都各向左移动一格。

    ⑦ 匹配顺序为从左到右;重复匹配到无法匹配为止,最后输出留下来几个牌堆,及每个牌堆的数量。

    ⑧ 只有一个牌堆时输出"pile",多堆时输出"piles"。

注意:

    ① 每次移动后要从左到右再次匹配检查。

    ② 输出时注意"s"。

思路:

    (参考了网上大牛们的题解)

    直接模拟题意内容进行从左到右的匹配,如移动变更过牌,则重新匹配。直到无法匹配为止。


总结:

    ① 使用了list和stack嵌套,使用STL可简化代码,可视化强,但效率会偏低。

       针对每个牌堆使用了stack,很形象的数据。

    ② 必须使用数组来模拟一次,以锻炼代码能力。

    ③ 注意使用嵌套时,有时会出现这种代码list<stack<char>>,会出现两个“>”并排,要在中间加个空格以区分"> >",不然编译器会出错!

       在VS可以通过,但在OJ上直接Compilation error。

    ④ 英文能力还不行,题目理解不透。

    ⑤ 要多读读大牛的代码,就和游戏一样,输的时候看录像才知真相才进步。



STL版本<使用list和stack>:Memery 0KB/Time 1238ms

#include <iostream>
#include <stdio.h>
#include <list>
#include <stack>
using namespace std;


// Local Test
// #define LOCAL_TEST


// Define for every one Card
struct CCard 
{
	char m_value;
	char m_suit;
	CCard(char a, char b):m_value(a), m_suit(b){}
};


bool Judge(CCard a, CCard b)
{
	if ( a.m_suit == b.m_suit || a.m_value == b.m_value )
		return true;
	return false;
}


// Get its immediate neighbour on the left
list<stack<CCard> >::iterator pre1(const list<stack<CCard> >::iterator it)
{
	list<stack<CCard> >::iterator temp = it;
	return --temp;
}


// Get its third pre to the left
list<stack<CCard> >::iterator pre3(const list<stack<CCard> >::iterator it)
{
	list<stack<CCard> >::iterator temp = it;
	return ------temp;
}


int main()
{
#ifdef LOCAL_TEST
	freopen("..\\in.txt", "r", stdin);
	freopen("..\\out.txt", "w+", stdout);
#endif
	// ------- Solution by using Sync(false)
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);

	// {s[3]} for getting input data
	char s[3];
	// {Game} store all cards, from left to right
	list<stack<CCard> > Game;
	// {it} for Traverse the list
	list<stack<CCard> >::iterator it;
	while ( scanf("%s", s), s[0]!='#' )
	{
		// Create a Card
		CCard cardTemp(s[0], s[1]);
		// Create a Stack of one place
		stack<CCard> stackTemp;
		stackTemp.push(cardTemp);
		// Then push into the {Game}
		Game.push_back(stackTemp);

		// If input 52 cards(all data in), then start to simulate
		if ( Game.size() == 52 )
		{
			// bool value, to determine to start checking
			// Set "true" , default to check
			bool bHasMoved = true;
			// While Has moved any card, then start a new check
			while ( bHasMoved )
			{
				// Set "false"
				bHasMoved = false;
				int count;
				for ( it=Game.begin(), count=0; it!=Game.end() && count<=52; it++, count++ )
				{
					// "count>2" means "it" has three pre to the left
					// Then to judge "it" and pre3 to "it"
					if ( count>2 && Judge(it->top(), pre3(it)->top()) )
					{
						// Move the current "it" to pre3(on its top)
						pre3(it)->push(it->top());
						// Pop "it" from current stack(this place)
						it->pop();
						// while this place is empty, then remove this place
						if ( it->empty() )
							Game.erase(it);
						// Set "true", then start a new check
						bHasMoved = true;
						break;
					} // end if
					if ( count>0 && Judge(it->top(), pre1(it)->top()) )
					{
						// Move the current "it" to pre1(on its top)
						pre1(it)->push(it->top());
						// Pop "it" from current stack(this place)
						it->pop();
						// while this place is empty, then remove this place
						if ( it->empty() )
							Game.erase(it);
						// Set "true", then start a new check
						bHasMoved = true;
						break;
					} // end if
				} // end for
			} // end while

			// output all data
			cout <<Game.size() <<" pile" <<(Game.size()>1?"s":"") <<" remaining:";
			for ( it=Game.begin(); it!=Game.end(); it++ )
			{
				cout <<" " <<it->size();
			} // end for
			cout <<"\n";
			// Clear all data of Current Game
			Game.clear();
		} // end if
	} // end while

	return 0;
}


原始代码:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值