【蓝桥每日一题]-动态规划 (保姆级教程 篇7)#栈

以后就开始讲动态规划的进阶应用了

目录

题目:栈

解法1: dfs

解法2:动态规划


  

题目:栈

  

【蓝桥每日一题]-动态规划 (保姆级教程 篇7)#栈_第1张图片【蓝桥每日一题]-动态规划 (保姆级教程 篇7)#栈_第2张图片【蓝桥每日一题]-动态规划 (保姆级教程 篇7)#栈_第3张图片

  

解法1: dfs 

 我们设置dfs( i , j )中 i表示队列剩余元素数,j表示栈中元素数。那么(n, 0)表示开始状态(0,x)表示结束状态,所以不用管出栈的个数。

   

另外设置f[i][j] 表示dfs(i,j)时候的情况数,一共最多18*18种情况,所以这样记忆化可以减少很多不必要的递归。

   

 转移方程: if(j>0) f[i][j]+=dfs(i,j-1);  下一个状态是从栈中取出,j>0可以有两种状态
                  f[i][j]+=dfs(i-1,j+1); 下一个状态是往栈中放入

#include                    
#define ll long long 
using namespace std;
int n;
ll f[20][20];  
ll dfs(int i,int j)
{
	if(f[i][j])return f[i][j];   //枝剪
	if(i==0)return 1;             //边界,递归是从边界开始的
	if(j>0)f[i][j]+=dfs(i,j-1);   //下一个状态是从栈中取出,j>0可以有两种状态,反之只有一种
	f[i][j]+=dfs(i-1,j+1);         //下一个状态是往栈中放入
	return f[i][j];               //返回结果,情况数
}
int main()
{
	cin>>n;
	cout<

   

解法2:动态规划

     

#include                      
#define ll long long 
using namespace std;
int n;
ll f[20][20];    //f[i][j]中i表示栈里的数,j表示队列里的数,f表示对应的情况数
int main()
{
	cin>>n;                              //f[i][j]中i表示入栈数,j表示出栈数,f表示对应情况数
	for(int i=0;i<=n;i++) f[i][0]=1;       //初始化dp,出栈为0入栈为i均为1种情况(因为只能连续出栈),出栈大于入栈不合理
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			if(i==j) f[i][j]=f[i][j-1];      //入栈等于出栈表示栈空,这个状态只能由出栈而来,
			else f[i][j]=f[i-1][j]+f[i][j-1]; //既可以由出栈而来,也可以由入栈而来
		}
	}
	cout<

   

另一种动态规划思路: 

int main()
{
	cin>>n;
	for(int i=0;i<=n;i++) f[i][0]=1;          //初始化,队列里的数全在栈里的情况均为1,因为只能出栈
	for(int j=1;j<=n;j++)
	  for(int i=0;i<=n;i++)                  //循环顺序不可变
	  {  if(i>=1) f[i][j]=f[i-1][j]+f[i+1][j-1];   //栈里的数不为空,则可以出栈,也可以入栈
	     if(i==0) f[i][j]=f[i+1][j-1];             //栈里的数为空,只能入栈了
	  }
	  cout<

 最近要期末考试了,唉,只能讲的仓促一点。

你可能感兴趣的:(动态规划,算法)