Problem Description
Aoshu is very popular among primary school students. It is mathematics, but much harder than ordinary mathematics for primary school students. Teacher Liu is an Aoshu teacher. He just comes out with a problem to test his students:
Given a serial of digits, you must put a '=' and none or some '+' between these digits and make an equation. Please find out how many equations you can get. For example, if the digits serial is "1212", you can get 2 equations, they are "12=12" and "1+2=1+2". Please note that the digits only include 1 to 9, and every '+' must have a digit on its left side and right side. For example, "+12=12", and "1++1=2" are illegal. Please note that "1+11=12" and "11+1=12" are different equations.
Input
There are several test cases. Each test case is a digit serial in a line. The length of a serial is at least 2 and no more than 15. The input ends with a line of "END".
Output
For each test case , output a integer in a line, indicating the number of equations you can get.
Sample Input
1212
12345666
1235
END
Sample Output
2
2
0
题意:
给你一串数字,你要在该串数字中间的某些位置加一个等号=和一个或多个+号或0个,使得那串数字编成一个等式。问你有多少种方式?
所以我们只需要先枚举=的位置mid,然后分别计算等号左边[0,mid-1],和等号右边[mid,len-1]可能的值即可。
注意我们先构造等号左边的值,当构造完当前左边值的基础上(即本dfs_left内),再去构造右边,看看有多少个右值等于该特定的左值。
代码中预处理了value[i][j]表[i,j]区间的连续数字构造的值。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn= 20;
char num[maxn];
long long value[maxn][maxn];
int ans;//解
int len;//输入字符长度
long long get_value(int x,int y)
{
long long sum=0;
for(int i=x;i<=y;i++)
sum = sum*10+num[i]-'0';
return sum;
}
void dfs_right(int pos,int left_sum,int sum)//left_sum左边已经算出来的和
{
if(pos>=len)
{
if(left_sum==sum) ans++;
}
else for(int i=pos;i<len;i++)
dfs_right(i+1,left_sum,sum+value[pos][i]);
}
void dfs_left(int pos,int sum,int mid)//pos当前位置,sum当前和,mid当前=号位置
{
if(pos>=mid)//处理完左边,开始处理右边了
{
dfs_right(mid,sum,0);
}
else for(int i=pos;i<mid;i++)//sum+本段值+下一段,即本段值是[pos,i]之间数的值,这之间没+号
dfs_left(i+1,sum+value[pos][i],mid);
}
int main()
{
while(scanf("%s",num)==1&&num[0]!='E')
{
ans=0;
len=strlen(num);
for(int i=0;i<len;i++)
for(int j=i;j<len;j++)
value[i][j]=get_value(i,j);
for(int mid=1;mid<len;mid++)//mid是等号位置,也即右边第一个数的位置
dfs_left(0,0,mid);
printf("%d\n",ans);
}
return 0;
}