UVa 127 手风琴纸牌 “Accordian“Patience

这道题是我看了刘汝佳写的算法竞赛入门经典后做的第一道题,一开始真的是什么都不会,连链表怎么建都不清楚,所以捣鼓了几天才搞定,这道题很适合练习链表的相关操作,对于刚入门的人来说还是非常不错的。

我想强调一点就是读题真的是非常重要,我第一次写的代码自己觉着一点问题没有,但是输出和例子都不一样!我用牌模拟了一下结果和我的答案是一样的!我就搞不清楚是怎么个情况了,后来才发现是题意理解错了!!无奈只好重新写,好在第二次就熟练多啦,删除节点什么的就比第一次容易的多!

题意我就不翻译了,不难读懂,网上也有翻译。

大体思路很简单了,就是建一个双向链表,每个节点都是一个堆栈,当堆栈为空时就删除该节点。在移动的时候要注意先判断能不能移三张,如若不行再移一张,每次移动完要立刻检查是否为空,是否还可以再向前移,如此循环直到移至尾节点。输出要注意细节,第一次提交就是因为输出末尾少打了一个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;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值