luogu1449:后缀表达式:栈的基础思维

题目连接

  • 该题是luogu试炼场的2-13:T5

题目大意

  1. 一个数学表达式,按照就近原则运算;
  2. 对于一个串,从左到右,只要遇到运算符,则马上用该运算符对左边的两个数进行运算;
  3. 求这样的运算终值。

题目分析

  • 看题目第一反应是栈;

  • 还有字符转数字的简单操作


解题思路1

  1. 用串来读入;
  2. 遇到连续的数字,则进行整理;
  3. 数字终端则将其进栈;
  4. 遇到符号,则取栈顶的两个数字进行运算。

代码1

  • 手工栈,思路要清醒
//luogu1449:后缀表达式 

//栈的基础使用 
 
#include
using namespace std;
 
char s[1005];
int n,a[1005];
  
int main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	
	int top=0,x=0;
	for(int i=1;i='0'&&s[i]<='9')//记录数字 
		{
			x=x*10+s[i]-'0';
		}		
		if(s[i]=='.')//数字结束,进栈 
		{
			a[++top]=x;
			x=0;
		}
		if(s[i]=='+')//进行运算,降低栈位 
		{
			a[top-1]=a[top]+a[top-1];
			top--;
		}
		if(s[i]=='-')//进行运算,降低栈位 
		{
			a[top-1]=a[top-1]-a[top];
			top--;
		}
		if(s[i]=='*')//进行运算,降低栈位 
		{
			a[top-1]=a[top]*a[top-1];
			top--;
		}
		if(s[i]=='/')//进行运算,降低栈位 
		{
			a[top-1]=a[top-1]/a[top];
			top--;
		}
	}
	printf("%d",a[top]);

	return 0;
}



思路2:dfs+记忆化

  • 暴搜过不了的题,一般两条路:想剪枝/ 想DP
  • 先想剪枝!!因为已经有了DFS的底板,只是做拓展的思维分析,赛场上的不二之选!!
  • 本题是一个环状结构,会有很多循环的步骤,从这里开始想:
  1. 对于点 i ,剩余步数相同的情况下,答案都是一样的;
  2. 所以用 f 数组表示:第 i 个点,剩下 j 步的情况,减少重复的搜索量;
  3. 记忆化的f数组,帮助回溯的时候更新;

代码2:记忆化搜索

  • 把回溯的内容理解透,才是真正理解递归
//luogu1057:传球游戏:记忆化搜索 

// f[i][j]: 第 i 格, 剩余 j 步的 答案  
#include

int n,m,f[50][50];

void dfs(int x,int t)//当前是 x 位置,走了 t步 
{
	f[x][t]=0;//初始化当前位置
	 
	if(x==1&&t==m) //记忆化1:到达 
	{
		f[x][t]=1;
		return ;
	}
	if(t==m) return ;//剪枝 
	
	//搜左边 
	int a; if(x==1) a=n; else a=x-1;
	if(f[a][t+1]==-1) dfs(a,t+1);//左边边界 
	
	//搜右边
	if(f[x%n+1][t+1]==-1) dfs(x%n+1,t+1);//右边没记录

	//回溯更新
	f[x][t]=f[a][t+1]+f[x%n+1][t+1];
}

int main()
{
	memset(f,-1,sizeof(f));
	scanf("%d %d",&n,&m);
	
	dfs(1,0);//从 1 出发,走了 0 步 
	
	printf("%d",f[1][0]);
	
	return 0; 
}







思路3:DP 分析

  • 暴力搜索过不了的题,剪枝可以增加得分量,但如果剩余很多时间(1个小时以上)或者平时练习,还是要掌握相应的DP的思维,多动脑~

  • DP思路: 问什么设什么!

  • f [ i ] [ j ] 表示:第 i 步 走到 j 位置 的方案数,很容易可以想到:任何一个 f[i][j]都是从左和右来的,就是 i-1 步的 j-1和 j+1 位置:

  • 所以通式就可以写成:f[i][j]=f[i-1][j-1]+f[i-1][j+1]

  • 初始化和边界随便搞一下。

代码3:

  • DP代码少,可是你能想到才行~
//luogu1057:传球游戏 

//DP思路: 
//f[i][j]表示:第 i 步 在 j 位置 的方案数 
//任何一个 f[i][j]都是从左和右来的,就是 i-1 步的 j-1和 j+1 位置: 

//所以通式就可以写成
//f[i][j]=f[i-1][j-1]+f[i-1][j+1] 
 
#include

int n,m;
int f[50][50];

int main()
{
	scanf("%d %d",&n,&m);
	memset(f,0,sizeof(f));
	
	f[0][1]=1;
	
	for(int i=1;i<=m;i++)//当前第 i 步 
	{
		for(int j=1;j<=n;j++)//当前第 j 个格 
		{
			if(j==1) f[i][j]=f[i-1][n]+f[i-1][2];//左边界 
			else if(j==n) f[i][j]=f[i-1][n-1]+f[i-1][1];//右边界
			else f[i][j]=f[i-1][j-1]+f[i-1][j+1]; 
		}
	}

	printf("%d",f[m][1]);
	
	return 0; 
}


神仙的思路4

推荐一个大佬的思考方式,绝对能帮助你比赛拿高分的那种!

  • 他是用宽搜+打表+DP的详细分析,如果赛场能按照这样的思路来答题,一定可以最少多拿50分!

你可能感兴趣的:(题解,题表,luogu,luogu1449,后缀表达式,栈)