我不写代码,我只是代码的搬运工[笑cry]——学习他人Uva 127 Accordian Patience 纸牌游戏,STL vector 解法

来源:互联网 发布:国泰安数据库价钱 编辑:程序博客网 时间:2024/06/07 23:51

Uva 127 Accordian Patience 纸牌游戏

题意:

按从左至右的顺序发牌,并摆成一行,发牌不要相互重叠。游戏中一旦出现任何一张牌与它左边的第一张或第三张“匹配”,即花色或点数相同,则须立即将其移动到那张牌上面。如果牌被移动后又出现了上述情况,则需再次向左移动。每叠牌只能移动最上面的一张。如果一叠牌被移空,应该立即将右边各叠整体向左移动,补上这个空隙。依次将整副牌都发完,并不断的向左合并。如果全部移动结束后整副牌都放成了一叠,则游戏胜利。


Input
输入到程序中的数据指定了一副牌的顺序。每组输入包括两行,每行26张牌,牌与牌之间用空格隔开。以#号开头的一行作为输入的结束行。每张牌由两个字符表示,第一个字符是点数:(A、 2-9、T=10、J、Q, K);第二个字符是花色:(C=梅花、D=方块、H=红心、S=黑桃)。

Output
每两行输入(定义了一副52张牌的顺序)必须产生一行输出。每行输出包括剩下的叠数以及每叠中的牌数。

Sample Input
QD AD 8H 5S 3H 5H TC 4D JH KS 6H 8S JS AC AS 8D 2H QS TS 3S AH 4H TH TD 3C 6S
8C 7D 4C 4S 7S 9H 7C 5D 2S KD 2D QH JD 6D 9D JC 2C KH 3D QC 6C 9S KC 7H 9C 5C
AC 2C 3C 4C 5C 6C 7C 8C 9C TC JC QC KC AD 2D 3D 4D 5D 6D 7D 8D TD 9D JD QD KD
AH 2H 3H 4H 5H 6H 7H 8H 9H KH 6S QH TH AS 2S 3S 4S 5S JH 7S 8S 9S TS JS QS KS
#


Sample Output
6 piles remaining: 40 8 1 1 1 1
1 pile remaining: 52


原来想法:

刚开始想用堆栈做,stack<node> card[52],开辟了52个堆栈空间,并写了bool型的Match函数判断是否能够“匹配”,void型的Move函数来做移动操作,void型的Check函数查看有几堆不为empty及不为empty的堆中元素有多少个,bool型函数Judge()从头开始判断是否还能Move,如果能,返回true,否则返回false。


存在问题:

没看清题目要求,当某一堆被移空后,该堆应该被消除,即后面的堆往前“补位”,之前的思路并没有考虑到这个问题,写的是如果某堆为空则Match返回false,结果导致出现的剩余堆数比较大。


尝试修改:

由于不同stack的删除比较困难,以及移动操作时间复杂性很高,于是放弃此种写法。


参考写法:

http://blog.csdn.net/bb2b2bbb/article/details/26484267

使用 vector< vector<node> > vec 的形式,开辟一个vector容器,其中的每个元素是一个vector<node>类元素。这样使用put_back函数和erase函数可以方便的插入删除。


Solution:

#include <iostream>#include <vector>#include <fstream>#include <time.h>using namespace std;    struct node{     char rank;  //点数: ( A = Ace, 2~9, T = 10, J = Jack, Q = Queen, K = King )     char suit;  //花色: ( C = Clubs, D = Diamonds, H = Hearts, S = Spades )     node(char r = ' ', char s = ' '):rank(r), suit(s){}  //构造函数}; vector < vector<node> > vec;int locate(node tmp, int num)<span style="white-space:pre"></span>//该函数返回当前node可以匹配的<strong>最前</strong>位置{    int pos;    while(num >= 0)    {         if(num >= 3)<span style="white-space:pre"></span>//先考虑可以匹配左边三位的情形         {                pos = vec[num - 3].size() - 1;    //pos定位在前三堆纸牌的最上面那张纸牌的位置                if(vec[num - 3][pos].rank == tmp.rank || vec[num - 3][pos].suit == tmp.suit)                {                     num = num - 3;<span style="white-space:pre"></span>  //如果匹配则将num定位于此                     continue;                }         }         if(num >= 1)<span style="white-space:pre"></span>  //同理,如果不能匹配左边三堆,则尝试匹配左边一堆         {                pos = vec[num - 1].size() - 1;                if(vec[num - 1][pos].rank == tmp.rank || vec[num - 1][pos].suit == tmp.suit)                {                     num = num - 1;                     continue;                }         }         break; //如果前面两种情况都不能符合,则再循环也不会符合,break,否则浪费时间。     }    return num; //将可以插入的位置序号返回}int main(){    freopen("Uva 127 Accordian Patience in.txt","r",stdin);    ofstream fcout("Uva 127 Accordian Patience out.txt");    unsigned int i;    char s[3];    while(cin >> s && s[0] != '#')    {         int number = 52;         while(number--)  //通过number来计数         {              node ele(s[0], s[1]);              int len = locate(ele, vec.size());   //<span style="color:#ff0000;">【优点在于每一次放纸牌都考虑能不能往前放,而不是所有纸牌放置完全之后再来移动】</span>              if(len == (int)vec.size())<span style="white-space:pre"></span>   //允许插入的位置等于size,也就是无法向前匹配,直接插入              {                     vector<node> tmp(1, ele);<span style="white-space:pre"></span>                     vec.push_back(tmp);              }              else<span style="white-space:pre"></span>   //否则向前堆叠              {                  vec[len].push_back(ele);                  Redo: for(i = len + 1; i < vec.size(); i++)  //由于堆叠在前面,所以堆叠之后,后面的堆可能可以向前移动,用for循环进行判断                       {                             node next = vec[i][vec[i].size()-1]; //可能的插入点是下一个vector顶上的元素。                              unsigned int new_location = locate(next, i);                             if(i != new_location)                             {                                  vec[new_location].push_back(next);                                  vec[i].pop_back();                                  if(vec[i].size() == 0)                                      vec.erase(vec.begin() + i);  //vec整体删除,vec.begin()的位置往后+i即为现在为空的位置                                   len = new_location;                                  goto Redo;                             }                       }              }              if(number == 0) continue;  //<span style="color:#ff0000;">如果输入没结束,但是一副纸牌已经输入完成,则退出内循环,重新进入外循环</span>              cin >> s;         }         fcout << vec.size() << (vec.size() != 1? " piles remaining : " : " pile remaining : ") ;         for(i = 0; i < vec.size(); i++)         {               if(i != vec.size() - 1)                    fcout << vec[i].size() << " ";               else fcout << vec[i].size() << endl;         }         fcout << "Time used = " << (double)clock()/ CLOCKS_PER_SEC << endl; //查看时间         vec.clear();    }        return 0;}


以上代码优点:每次只输入一张牌,马上向前查看是否能匹配,而不是一副牌都分配好后再来插入和删除,效率高,实现效果好。Locate函数可直接返回当前可以放入的位置,十分巧妙。

0 0
原创粉丝点击