【清北学堂周末刷题班】 Day3

A
原题地址:http://csp.ac/contest/46/problem/301
【问题描述】

你是能看到第一题的friends呢。

——hja

众所周知,小葱同学擅长计算,尤其擅长计算组合数,但这个题和组合数没什么关系。

给定一个只包含乘号、加号和数字的表达式,你需要替换其中一个位置的符号将表达式变为另一个表达式(可以替换为同样的字符,但前导零是不允许的),求所有合法情况得出的表达式的值的和。

【输入格式】

一行一个字符串代表表达式。

【输出格式】

一行一个整数代表答案。

【样例输入】

233

【样例输出】

9633

【样例解释】

不合法的串仅包括033,∗33,23∗,23+,+33033,∗33,23∗,23+,+33。

【数据规模与约定】

对于40%的数据,字符串长度不超过3。

对于80%的数据,字符串长度不超过10。

对于100%的数据,字符串长度不超过100。

【思路】:首先枚举for(i到len)以及for(int j=1到0-9,+,x )
这个时候有两个问题:
这个时候我们可以把它转化成后缀表达式再去计算它的值,可以用一个栈去维护它的计算过程。由于这个题它只有乘法和加法,我们可以先把所有的乘法做完,再去做所有的加法。
【1】不合法的情况1:符号重复时1++,1+1,+1,+11...等等
【2】不合法的情况2:出现前导0:+0,*0,0++...等
【3】还有一种情况,但是是合法的:1+0+3,此时的‘0’作为一个单独的数存在。这时看它前后是否有数存在。但此时如果把它看做不合法时也依旧可以拿50分
开long long 时可以拿80%的分。这个时候可以进行一定的抉择,它是一个高精度,我们可能无法很好的取得这个20%的分数,我们在这时可以进行抉择,比如是先往后看,还是继续钻研这个高精度。在这时放弃是最好的选择。在考试时要懂得变通,题目的难度不一定绝对单调递增,在这个时间就算玩扫雷也比这划算
但是如果想拿高分段,就需要对这道题进行死磕,这种题练得越多能力也会越强。
今天有点晚了,就先睡了,代码什么的明天中午再说。(c++它是自己先崩的,不关我的事)
好吧,我这个和他这个差不多。。一个大佬的地址https://www.cnblogs.com/wweiyi2004/p/13873774.html

几乎都是只对一下题目和算法。。

下面就是(简单)的一个将表达式转换为后续表达式的算法。

我太菜了,只能对模板了。。因为这题只有乘号和加号,所以我就只添加了存在乘法和加法存在的可能性

以下为栈维护的内容,至于这道题...我做不出来orz

以下就是输入一个合法只包含‘*’,‘+’,数字的表达式,求出它们的值

#include<iostream>
#include<stdio.h>
#define MAX 101
//输入一个表达式,输出它经过计算后的值(输入只存在*和+,而且保证输入的算式合法)
using namespace std;
char exp[MAX];

void trans()//将算术表达式转换为后缀表达式
{
	char str[MAX];
	char stack[MAX];
	char ch;
	int sum,i,j,t,top=0;
	i=0;
	do
	{
		i++;
		scanf("%c",&str[i]);
	}while(str[i]!='
'&&i!=MAX);//一个很实用的‘输入一排数据’
	sum=i;
	t=1;i=1;
	ch=str[i];i++;
	while(ch!='
')
	{
		switch(ch)
		{
			case'+':
				while(top!=0)
				{
					exp[t]=stack[top];top--;t++;
				}
				top++;stack[top]=ch;
				break;
			case'*':
				while(stack[top]=='*')
				{
					exp[t]=stack[top];top--;t++;
				}
				top++;stack[top]=ch;
				break;
			case' ':break;
			default:
				while(ch>='0'&&ch<='9')
				{
					exp[t]=ch;t++;
					ch=str[i];i++;
				}
				i--;
				exp[t]='
';t++;
		}
		ch=str[i];i++;
	}
	while(top!=0)
	{
		exp[t]=stack[top];t++;top--;
	}
	exp[t]='
';
	/*
	cout<<"
";
	for(j=1;j<sum;j++)printf("%c",str[j]);  //这是输出原来输入时(正常)的输入

	cout<<"
";
	for(j=1;j<t;j++)printf("%c",exp[j]);  //这是输出后续表达式
	*/
}

void compvalue()//计算后继表达式的值
{
	float stack[MAX],d;//作为栈使用
	char ch;
	int t=1,top=0;//t作为exp的下标,top作为stack的下标
	ch=exp[t];t++;
	while(ch!='
')
	{
		switch(ch)
		{
			case'+':stack[top-1]=stack[top-1]+stack[top];
			       top--;break;
			case'*':stack[top-1]=stack[top-1]*stack[top];
			       top--;break;
			default:d=0;
					while(ch>='0'&&ch<='9')//判定为数字字符
					{
						d=10*d+ch-'0';//将数字字符转换为对应的数值
						ch=exp[t];t++;
					}
					top++;
					stack[top]=d;
		}
		ch=exp[t];t++;
	}
	printf("%g
",stack[top]);//最后输出对于这个表达式的计算结果
}

int main()
{
	trans();
	compvalue();
	system("pause");//当程序结束时不会立即退出,而是可以显示输出结果,等待退出。
}
原文地址:https://www.cnblogs.com/royann/p/13876109.html