题目连接
- 该题是luogu试炼场的2-13:T5
题目大意
- 一个数学表达式,按照就近原则运算;
- 对于一个串,从左到右,只要遇到运算符,则马上用该运算符对左边的两个数进行运算;
- 求这样的运算终值。
题目分析
-
看题目第一反应是栈;
-
还有字符转数字的简单操作
解题思路1
- 用串来读入;
- 遇到连续的数字,则进行整理;
- 数字终端则将其进栈;
- 遇到符号,则取栈顶的两个数字进行运算。
代码1
- 手工栈,思路要清醒
//luogu1449:后缀表达式
//栈的基础使用
#include<bits/stdc++.h>
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<n;i++)
{
if(s[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的底板,只是做拓展的思维分析,赛场上的不二之选!!
- 本题是一个环状结构,会有很多循环的步骤,从这里开始想:
- 对于点 i ,剩余步数相同的情况下,答案都是一样的;
- 所以用 f 数组表示:第 i 个点,剩下 j 步的情况,减少重复的搜索量;
- 记忆化的f数组,帮助回溯的时候更新;
代码2:记忆化搜索
- 把回溯的内容理解透,才是真正理解递归
//luogu1057:传球游戏:记忆化搜索
// f[i][j]: 第 i 格, 剩余 j 步的 答案
#include<bits/stdc++.h>
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<bits/stdc++.h>
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分!

博客介绍了Luogu1449题目的解法,主要涉及后缀表达式的运用。通过栈来处理数学表达式,遇到数字时整理并入栈,遇到运算符则取栈顶两数运算。还探讨了dfs+记忆化搜索与DP的解题策略,使用记忆化搜索优化搜索过程,并通过DP解决问题。

531

被折叠的 条评论
为什么被折叠?



