这题只是一道简单的模拟题而已(真的只是简单而已 =-= T^T),虽然我花了好长时间。
我使用数组模拟链表,模拟对纸牌的操作。
要注意的是堆剩余数为1时,输出的不是“piles",而是"pile"。
我的解题代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <string> #include <algorithm> using namespace std; char Rank[55],Suit[55]; int Next[55],L[55],R[55],Num[55]; //Next[i]存放纸牌i下方的纸牌编号,L,R存放i的左右堆上第一张牌,Num存放i所在堆的纸牌数 int piles_remain; //堆剩余数 void move(int i, int j) {//将以编号为i的的纸牌移动到编号为j的纸牌上方 if(Next[i]==-1) //移动前i的下面没有其他牌 { R[L[i]] = R[i]; L[R[i]] = L[i]; piles_remain--; } else //移动前i下面有其他牌 { R[L[i]] = Next[i]; L[R[i]] = Next[i]; L[Next[i]] = L[i]; R[Next[i]] = R[i]; Num[Next[i]] = Num[i]-1; Num[i] = 1; } R[L[j]] = i; L[R[j]] = i; L[i] = L[j]; R[i] = R[j]; Next[i] = j; L[j] = R[j] = -1; Num[i] += Num[j]; Num[j] = 0; } int left1(int s) {//返回纸牌s左边堆的最上面一张牌编号 return L[s]; } int left3(int s) {//返回纸牌s左边第三堆最上面一张牌编号 int c=3,tmp=s; while(c--) { tmp=L[tmp]; } return tmp; } int main() { int tmp,count,L1,L3; while(cin>>Rank[1] && Rank[1]!='#') { cin >> Suit[1]; Num[1] = 1; for(int i=2; i<=52; i++) { cin >> Rank[i] >> Suit[i]; Num[i] = 1; } memset(Next,-1,sizeof(Next)); for(int i=1; i<=52; i++) { R[i] = i+1; L[i] = i-1; } piles_remain = 52; R[0] = 1; while(piles_remain>1) { int i; for(i=R[0]; i!=53; i=R[i]) { L1 = left1(i); L3 = left3(i); if(L3!=0 && (Rank[i]==Rank[L3] || Suit[i]==Suit[L3])) { // cout << i << " -> " << L3 << endl; move(i,L3); break; } else if(L1!=0 && (Rank[i]==Rank[L1] || Suit[i]==Suit[L1])) { // cout << i << " -> " << L1 << endl; move(i,L1); break; } } if(i==53) break; } if(piles_remain==1) cout << 1 << " pile remaining:"; else cout << piles_remain << " piles remaining:"; for(int i=R[0]; i!=53; i=R[i]) cout << ' ' << Num[i]; cout << endl; } return 0; }