传送门:
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;
}