Elimination 堆栈

18 篇文章 0 订阅

题目描述

消除游戏需要 N 张大小为 1 ∼ N 的纸牌。
游戏开始时, N 张纸牌排成一行。对于某张纸牌,如果其牌面大小比右边相邻的纸牌小,那么这张纸牌将被消除。
游戏按照上述规则进行多轮消除,直到不存在满足条件的纸牌,游戏结束。
现在已知纸牌的初始排列顺序,请问消除游戏需要几轮结束,最后剩下的牌是什么。

输入

第一行一个正整数 T (T ≤ 10),表示测试数据的组数。
对每组测试数据,第一行一个整数 N(1 ≤ N ≤ 106),表示有 N 张纸牌。
第二行 N 个整数 ai(1 ≤ ai ≤ N, ∀i != j, ai != aj),表示从左到右纸牌的牌面大小。

输出

对于每组数据,输出两行。
第一行输出一个整数,表示消除游戏进行多少轮之后结束。
第二行按照从左到右的顺序,输出游戏结束时剩余纸牌的牌面大小。

样例输入

3
4
4 3 2 1
4
1 2 3 4
7
2 1 4 3 5 7 6

样例输出

0
4 3 2 1
1
4
2
7 6

 

找出所有能消除左边的数,对这里面每一个数而言,每一次操作或者能够删除一个数或者该数不再能够删除左边的数
利用堆栈或者递归函数

#include <iostream> 
#include <cstring>
#include <stack> 
using namespace std; 

#define MAX 1000005     

struct node{
	int val,num,del; 
};   

int a[MAX]; 
int large[MAX]; 
int out[MAX]; 

int dfs(int l,int r){
	if (l>=r) return 0;   
	stack<node>s;  
	while (!s.empty()){
		s.pop(); 
	}
	int m=a[r],i=r-1,n=0,maxn;      
	while(i>=l&&!large[i]){
		n++; i--; 
	} 
	if (i<l)  return n;    
	node temp={m,++n,r-l+1};      
	s.push(temp); 
	m=a[i]; i--; 
	maxn=n; n=0;  
	while (i>=l) 
	{
		if (large[i]==0)
		{   
			if(a[i]<m&&n<maxn){  
				n++; i--;  
			}else{
				temp=s.top();  s.pop(); 
				n=temp.num;  m=temp.val;  maxn=temp.del;  
			} 
		}else{ 
			if (a[i]<m&&n<maxn) {     
				n++; 
				if (n<maxn) {
					node temps={m,n,maxn};   
					s.push(temps);    
				} 
				maxn=n; n=0; m=a[i--];    

			}else{
				temp=s.top();  s.pop(); 
				n=temp.num;  m=temp.val;  maxn=temp.del;  
			}
		}
	}    

	node temps={m,n,maxn};   
	s.push(temps);      

	while(!s.empty()){  
		temp=s.top();  s.pop(); 
	} 
	return temp.num; 
} 

int main()
{
	int t,n,m,k,ma,temp,r,p;
	cin>>t; 
	while (t--)
	{  
		memset(large,0,sizeof(large));     
		cin>>n>>a[1];
		k=0; ma=0; p=0;a[0]=n+1; 
		for (int i=2;i<=n;i++)
		{ 
			cin>>a[i];  
			if (a[i]>a[i-1]){
				large[i]=1;  
				p=1;
			} 
		}  
		if (p==0)
		{
			cout<<0<<endl;  
			for (int i=1;i<n;i++)  
				cout<<a[i]<<" ";   
			cout<<a[n]<<endl; 
			continue; 
		}

		m=a[n];  r=n;  out[k++]=m; 
		for (int i=n-1;i>=0;i--)
		{ 
			if (a[i]>m){
				out[k++]=a[i];       
				temp = dfs(i+1,r);  
				if(temp>ma) ma=temp; 
				r=i; m=a[i];  
			}
		}  
		cout<<ma<<endl;      
		for (int i=k-2;i>0;i--)                    
			cout<<out[i]<<" ";   
		cout<<out[0]<<endl; 
	}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值