这道题是我看了刘汝佳写的算法竞赛入门经典后做的第一道题,一开始真的是什么都不会,连链表怎么建都不清楚,所以捣鼓了几天才搞定,这道题很适合练习链表的相关操作,对于刚入门的人来说还是非常不错的。
我想强调一点就是读题真的是非常重要,我第一次写的代码自己觉着一点问题没有,但是输出和例子都不一样!我用牌模拟了一下结果和我的答案是一样的!我就搞不清楚是怎么个情况了,后来才发现是题意理解错了!!无奈只好重新写,好在第二次就熟练多啦,删除节点什么的就比第一次容易的多!
题意我就不翻译了,不难读懂,网上也有翻译。
大体思路很简单了,就是建一个双向链表,每个节点都是一个堆栈,当堆栈为空时就删除该节点。在移动的时候要注意先判断能不能移三张,如若不行再移一张,每次移动完要立刻检查是否为空,是否还可以再向前移,如此循环直到移至尾节点。输出要注意细节,第一次提交就是因为输出末尾少打了一个endl就wa,又搞了随机数据生成器比对了半天都和标准答案没有啥区别,郁闷了半小时。。。
代码如下
#include<iostream>
using namespace std;
struct Node{
char card[60][2];
int top;
Node* pre;
Node* next;
};
class List{
public:
Node* head;
Node* current;
Node* rear;
List(char arr[53][2]){
head = new Node;
rear = new Node;
head->next= rear;
head->pre=NULL;
rear->next=NULL;
for (int i=51;i>=0;i--){
Node* nnd = new Node;
nnd->card[0][0]=arr[i][0];
nnd->card[0][1]=arr[i][1];
nnd->top=1; //top=0 means empty
nnd->next=head->next;
head->next->pre=nnd;
head->next=nnd;
nnd->pre=head;
}
}
~List(){
Node* p = head;
while(p){
head=p;
p=p->next;
delete head;
}
}
bool is_empty(Node* s){
if (s->top==0){
return 1;
}
else return 0;
}
int check_move(Node* s){
Node* p = s->pre;
int checkone=0;
if (p==NULL||p->pre==NULL) return 0;
else if (p->pre->pre==NULL) checkone=1;
else if (p->pre->pre->pre==NULL) checkone = 1;
else {
Node* th=s->pre->pre->pre;
if (th->card[th->top-1][0]==s->card[s->top-1][0] || th->card[th->top-1][1]==s->card[s->top-1][1]) return 3;
else checkone=1;
}
if (checkone==1){
if(p->card[p->top-1][0]==s->card[s->top-1][0] || p->card[p->top-1][1]==s->card[s->top-1][1]) return 1;
}
return 0;
}
void move(Node *s){
if (check_move(s)==3){
Node* th=s->pre->pre->pre;
th->card[th->top][0]=s->card[s->top-1][0];
th->card[th->top][1]=s->card[s->top-1][1];
th->top++;
s->top--;
if (s->top==0){
s->pre->next=s->next;
s->next->pre=s->pre;
s->next=NULL;
s->pre=NULL;
delete s;
}
current=th;
}
else if (check_move(s)==1){
Node* one = s->pre;
one->card[one->top][0]=s->card[s->top-1][0];
one->card[one->top][1]=s->card[s->top-1][1];
one->top++;
s->top--;
if (s->top==0){
s->pre->next=s->next;
s->next->pre=s->pre;
s->next=NULL;
s->pre=NULL;
delete s;
}
current=one;
}
else current=current->next;
}
};
int main(){
char over[4];
char input[53][2];
while(cin>>over){
if (over[0]=='#'){break;}
input[0][0]=over[0];
input[0][1]=over[1];
over[0]=over[1]=NULL;
for (int i=1;i<52;i++){
cin>>input[i];
}
List* list = new List(input);
list->current=list->head->next;
while(list->current->next!=NULL){
list->move(list->current);
}
int num=0;
Node* p=list->head->next;
while(p->next!=NULL){
num++;
p=p->next;
}
if (num==1){cout<<num<<" pile remaining:";}
else cout<<num<<" piles remaining:";
Node* s=list->head->next;
for (int i=0;i<num;i++){
cout<<" "<<s->top;
s=s->next;
}
cout<<endl;
}
return 0;
}