洛谷P1044 栈

发布的第10篇博文,纪念一下

题意:

宁宁考虑的是这样一个问题:一个操作数序列,\(1,2,…,n\),栈 \(A\) 的深度大于 \(n\)

现在可以进行两种操作:
将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的 push 操作)
将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的 pop 操作)

你的程序将对给定的 \(n\),计算并输出由操作数序列 \(1,2,…,n\) 经过操作可能得到的输出序列的总数。

\(n≤18\)

思路:

这题的状态比较难设:
\(f[i][j]\)表示输出序列有i个数,栈内累计进入了j个数的方案数
不难看出,输出序列没有数,栈内累计不论有多少个数,都仅有一种情况,所以有以下代码(预处理):

	for(int i=0;i<=n;i++)
	{
		f[0][i]=1;
	}

每一次,我们都有两种操作:
1、向栈内弹进一个数,即为\(f[i][j-1]\)
2、从栈内弹出一个数。即为\(f[i-1][j+1]\)
但是,要注意当栈为空时(\(i=j\)),仅能向内弹进一个(因为没有东西可以弹出了)。
因此,转移方程便为
\(i=j\)
\(f[i][j]=f[i][j-1]\)
\(i≠j\)
\(f[i][j]=f[i][j-1]+f[i-1][j+1]\)

code:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
using namespace std;
const int N=20;
int n,f[N][N];
int main()
{
	cin>>n;
	for(int i=0;i<=n;i++)
	{
		f[0][i]=1;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
		      if(j==i)
		            f[i][j]=f[i][j-1];
		      else
			    f[i][j]=f[i-1][j+1]+f[i][j-1];
		}
	} 
	cout<<f[n][n];
    return 0;
}

posted @ 2020-03-26 07:54  panjx  阅读(147)  评论(0编辑  收藏  举报