HDU 1022 Train Problem I(判断出栈序列是否可行)

HDU 1022 Train Problem I(判断出栈序列是否可行)

题意:

        现在有一组数字序列,该序列中每个数字都是1到n之间的数,其中n<=9.有一个栈,给出该数字序列1到n的进栈顺序,并给出要求的出栈顺序,要你判断是否能按照这个顺序出栈。

        输入实例:

        3 123 321

        3 123 312

        输出实例:

        Yes.

        in

        in

        in

        out

        out

        out

        FINISH

        No.

        FINISH

        输入:输入包含多个实例。每个实例第一个数字为n,接下来是进栈的数字顺序,然后是要求的出栈数字顺序。

        输出:对于每个实例,按要求格式输出对应结果。

分析:

        首先如果出栈序列可行,那么必定存在唯一的可行出栈方式(想想是不是)。我们只需要一步步尝试出栈和入栈操作是否满足当前的出栈序列中的元素顺序即可(每步的尝试不是 出栈操作 就是 入栈操作 其实很简单了,且只有出栈不可行的时候,我们才去入栈)。

        我们只要用两个指针i和j,指向当前需要处理的入栈和出栈的那个字符即可。

        先看如果我们把栈S中的元素出栈,如果S出栈的元素正好是j所指的元素,那么就出栈且j++处理下一个i和j对即可。

        如果出栈不可行,那么我们就把i所指元素入栈即可。

        注意出栈和入栈需要满足下面条件:

        出栈:栈S不能为空  且  j不能超过出栈序列的最后一个元素 且 S.top() == j所指元素

        入栈:i不能超过入栈序列的最后一个元素

AC代码(新):

#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<cstdio>
using namespace std;

struct Station
{
    string a;//入栈序列
    string b;//出栈序列
    vector<string> res;//可行的方式

    Station(const string &a,const string &b):a(a),b(b){}

    //判断是否可行
    bool solve()
    {
        if(a.size()!=b.size() || a.size()>9) return false;

        int i=0,j=0;
        stack<char> S;
        while(i<a.size() || j<b.size())
        {
            //先看出栈是否符合要求
            if(!S.empty() && j<b.size() && S.top()==b[j] )
            {
                S.pop();
                res.push_back("out");
                ++j;
            }
            else//出栈不可行,那么就入栈看看
            {
                if(i==a.size())
                    return false;
                S.push(a[i]);
                res.push_back("in");
                ++i;
            }
        }

        return true;
    }
};

int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        string a;
        string b;
        cin>>a>>b;

        Station sta(a,b);

        if(!sta.solve())
            cout<<"No."<<endl;
        else
        {
            cout<<"Yes."<<endl;
            for(int i=0;i<(sta.res).size();i++)
                cout<<(sta.res)[i]<<endl;
        }
        cout<<"FINISH"<<endl;
    }
    return 0;
}

AC代码:

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

string in;//输入序列
string out;//输出序列
string com[100];//用来保存对栈的进出操作序列的

int main()
{
    int n;
    while(cin>>n)
    {
        int c_len=0;//对栈操作的序列长度
        cin>>in>>out;
        stack<char> s;//模拟栈
        int i=0,j=0;//指向输入序列,输出序列的指针
        while(i<n&&j<n)
        //要不输入序列到尾(i==n),输出未到尾(j<n),表示输入序列都到栈中去了。
        //要不就是输出序列到尾(j==n),此时输入序列必定也到尾(i==n),成功转换输入为输出
        {
            if(in[i]==out[j])//输入头与输出头相同,直接输出
            {
                com[c_len++]="in";
                com[c_len++]="out";
                i++;
                j++;
            }
            else if(s.empty()|| (s.top()!=out[j]) )//栈顶与输出头不同(包括栈空的清空)
            {
                com[c_len++]="in";
                s.push(in[i]);
                i++;
            }
            else//栈顶与输出头相同
            {
                com[c_len++]="out";
                s.pop();
                j++;
            }
        }
        while(!s.empty()&&s.top()==out[j])//输入序列已到底,需要从栈中进行判断
        {
            com[c_len++]="out";
            s.pop();
            j++;
        }
        if(s.empty())
        {
            cout<<"Yes."<<endl;
            for(int i=0; i<c_len; i++)
                cout<<com[i]<<endl;
            cout<<"FINISH"<<endl;
        }
        else
        {
            cout<<"No."<<endl;
            cout<<"FINISH"<<endl;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值