/* coder:ACboy date:2010-3-5 result: AC description: UVa 127 "Accordian" Patience */ #include <iostream> #include <string> using namespace std; // 每张牌的表示 struct node { char rank; char suit; }; // 用来表示一堆牌 struct myStack { node value[60]; int top; myStack(): top(0) {} }; // 用来表示一副牌 myStack data[60]; // 用来标记第i堆中是否还有牌,vis[i] == 0表示还有牌 int vis[60]; // 用于判断两张牌是否匹配 int checkMatch(node a, node b) { if (a.rank == b.rank || a.suit == b.suit) return 1; else return 0; } // 获取每张牌的匹配的牌的位置,不存在时返回-1。 int getMatchPos(int pos, node & a) { if (vis[pos]) return -1; else { int count; int firstPos, secondPos; // 每次匹配以最左为最优 // 左起的第三个位置 firstPos = -1; // 左起的第一个位置 secondPos = -1; count = 0; for (int i = pos - 1; i >= 0; i--) { if (!vis[i]) { count++; if (count == 1) secondPos = i; if (count == 3) firstPos = i; if (count > 3) break; } } // 如果左起的第一个和第三个位置都不存在,则返回-1表示不存在 if (firstPos == -1 && secondPos == -1) return -1; // 如果左起第三个位置存在,进行匹配检测 else if (firstPos != -1 && checkMatch(data[pos].value[data[pos].top - 1], data[firstPos].value[data[firstPos].top - 1])) { return firstPos; } // 如果左起第三个不存在,但是左起第一个存在,进行匹配检测 else if (secondPos != -1 && checkMatch(data[pos].value[data[pos].top - 1], data[secondPos].value[data[secondPos].top - 1])) { return secondPos; } // 如果都不匹配,返回-1表示不存在 else return -1; } } // 判断是否能一次性收起 int if_can_close_up() { int i; // 用temp数组来保存还有牌的堆的标号 int temp[60]; int count = 0; for (i = 0; i < 52; i++) { if (!vis[i]) temp[count++] = i; } int ok = 1; // 对连续的两堆牌进行检测匹配,如果每对连续的牌都匹配的话ok的值为1,否则为0。 for (i = 0; i < count - 1; i++) { if (!checkMatch(data[i].value[data[i].top - 1], data[i + 1].value[data[i + 1].top - 1])) { ok = 0; break; } } return ok; } int main() { int i, j; int d; char str[2][100]; #ifndef ONLINE_JUDGE freopen("127.txt", "r", stdin); #endif d = 0; while (1) { gets(str[0]); if (strcmp(str[0],"#") == 0) break; gets(str[1]); int c = 0; for (i = 0; i < 2; i++) { int len = strlen(str[i]); for (j = 0; j < len; j += 3) { //这道题我调试了3,4个小时,就是因为忘了添加下面一条语句, //所以在变量在最好是在声明的时间进行初始化。 data[c].top = 0; data[c].value[data[c].top].rank = str[i][j]; data[c].value[data[c].top].suit = str[i][j + 1]; data[c].top = 1; c++; } } // 初始化标记,每堆上都有牌 memset(vis, 0, sizeof(vis)); i = 0; // 用来标记是否是一次性收起 int flag = 0; // 从第一个牌开始进行匹配,直到最后一张牌 while (i < 52) { // 如果能一次性收起,介绍循环,所有的牌最后变成一堆 if (if_can_close_up()) { flag = 1; break; } // 否则查找匹配位置 int matchPos = getMatchPos(i, data[i].value[data[i].top - 1]); // 如果匹配位置不存在,从下一个牌开始匹配 if (matchPos == -1) i++; // 匹配位置存在 else { // 匹配位置上的那个堆多一张牌 data[matchPos].value[data[matchPos].top].rank = data[i].value[data[i].top - 1].rank; data[matchPos].value[data[matchPos].top].suit = data[i].value[data[i].top - 1].suit; data[matchPos].top++; // 原来的那堆牌数减一 data[i].top--; // 如果原来那堆牌数为零,则进行标记,标记该堆已经没有牌 if (data[i].top == 0) vis[i] = 1; // 从匹配的位置从新进行下一次匹配 i = matchPos; } } // 如果是一次性收起,表示最后只有一堆52张牌。 if (flag) { cout << "1 pile remaining: 52" << endl; } else { // 用来存储最后又多少堆 int count = 0; for (j = 0; j < 52; j++) { if (vis[j] == 0) count++; } cout << count << " piles remaining:"; // 输出每堆的牌数 for (i = 0; i < 52; i++) if (!vis[i]) { cout << " " << data[i].top; } cout << endl; } } return 0; }