1051 Pop Sequence (25分)判断出栈队列合法性。附多组测试样例,及生成测试样例的代码

本文用状态转移方程判断出栈合法性,区别于大部分用stack模拟的方法。阐述了将要出栈元素左右元素的出栈状态要求,给出合法与不合法状态示例,还提供了AC代码、生成测试数据的代码以及大量非法出栈队列测试用例。

1051 Pop Sequence (25分)用状态转移方程来解,附多组测试样例及生成测试样例的代码

前言

题目不再赘述。目前本题大部分用的是stack模拟出栈的合法性。本文用状态转移方程做了一波,并给出多组测试用例,以及可以用来生成测试样例的代码。
例如不合法序列:1 2 3 4 7 5 6
目前考察元素5的出栈情况。
对于每个将要出栈的元素(5)而言,应当满足:该元素左边的元素(1,2,3,4)可以部分已经出栈,但是剩余元素的个数不得大于栈的深度5。
该元素右边的各个元素(6,7)要么全部都没有出栈,要么全部都已经出栈,再要么最右侧的所有都没出栈,紧邻5的元素们全部都已经出栈。
我们假设尚未进行出栈操作表示为1,已经进行出栈操作表示为0。那么将要出栈的元素右边的元素。合法的状态是:

  1. 11111111111…全部都没有出栈(出栈序列比当前元素靠后)。比如将要出栈5,那么序列5,(6,7,8,9)可能是一个合法解。
  2. 000000000…全部都已经出过栈(出栈序列比当前元素靠前)。比如将要出栈5,那么序列(6,7,8,9),5可能是一个合法解。
  3. 00000…111…最右边的都没出栈,最左边的都已经出过栈。比如将要出栈5,那么序列(6,7),5,(8,9)可能是一个合法序列。
    不合法的状态是:
  4. 00000…111111…0000。也就是说(6,7),(11,12),5,(8,9,10)这是一个不合法序列。
  5. 11111…0000…。即(8,9,10),5,(6,7)这是一个不合法序列。
    状态0:000…,加0转至状态0,加1转至状态1。
    状态1:000…111…,加0转至状态2,加1转至状态1.
    状态2:000…111…000…已经非法,不管加0加1都是非法状态。可以与状态4合并。为了简便理解,这里不做合并。加0加1转至状态2。
    状态3:111…,加0转至状态4,加1转至状态3.
    状态4:111…000…,状态已经非法,不管加0加1都是非法状态,全部转移至状态4。
int stateTransfer[5][2] = {
   
    {
   
   0,1},{
   
   2,1},{
   
   2,2},{
   
   4,3},{
   
   4,4}};
//
//省略部分代码
//
int state;
if (check[t + 1] == -1)state = 3;
else state = 0;
for (int s = t + 2; s <= n; s++) {
   
   
	state = stateTransfer[state][check[s]==-1];
}
if (state==2 || state == 4) {
   
   
	flag = 0;
	continue;
}
else {
   
   
	check[t] = 0;
}


1.AC代码如下

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
int check[1010];
int appear[1010];
int stateTransfer[5][2] = {
   
    {
   
   0,1},{
   
   2,1},{
   
   4,4},{
   
   4,3},{
   
   4,4} };

int main()
{
   
   
	int m, n, k, t;
	scanf("%d%d%d", &m, &n, &k);
	for (int i = 0; i < k; i++) {
   
   
		int flag = 1;
		memset(check+1, -1, 4*n);
		memset(appear + 1, 0, 4 * n);
		for (int j = 0; j < n; j++) {
   
   
			scanf("%d", &t);
			if (!flag)continue;
			if (appear[t]) {
   
   
				flag = 0;
				continue;
			}
			else {
   
   
				appear[t] = 1;
		
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ProfSnail

谢谢老哥嗷

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值