题目链接 https://vjudge.net/problem/UVA-817
题意:输入一个以等号结尾。前面只包含数字的表达式,插入一些加号、减号和乘号,使得运算结果等于2000.表达式里的整数不能有前导零(例如,0100和000都是非法的),运算符都是二元的(例如,2*-100*-10+0=是非法的),并且符合通常的运算优先级法则。输入数字个数不超过9。如果有多解按照字典序从小到大输出:如果无解,输出IMPOSSIBLE。例如,2100100=有3组解,按照字典序依次为2*100*10+0=、2*100*10-0=和2100-100=。(本段摘自《算法竞赛入门经典(第2版)》)
分析:
枚举插入运算符的个数,进行DFS即可。计算表达式的值直接用两个栈解决。需要注意的是,貌似题目并没有要求按字典序输出,还有就是至少要插入一个运算符。
#include<cstring>
#include<algorithm>
#include<set>
#include<iostream>
#include<ctype.h>
#include<string>
using namespace std;
#define NUM 2000
char y[4]={
'*','+','-','#'
};
set<string> res;
char str[10];
char temp[40];
int n,kase=1;
void print(char temp[])
{
int l=strlen(temp);
char temp1[10];
int k=0;
for(int i=0;temp[i]!='=';i++)
{
if(temp[i]!='#')
temp1[k++]=temp[i];
}
temp1[k++]='='; temp1[k++]='\0';
if(res.count(temp1)==0)
res.insert(temp1);
}
bool check(char temp[])
{
int a=0,b;
if(temp[0]=='0'&&temp[1]=='#'&&isdigit(temp[2]))
return false;
int l=strlen(temp);
for(int i=2;i<l-2;i++)
{
if((temp[i-1]=='+'||temp[i-1]=='-'||temp[i-1]=='*')&&
(temp[i]=='0')&&(temp[i+1]=='#')&&
(isdigit(temp[i+2])))
return false;
}
return true;
}
int compute(char temp[])
{
int b[10];
char c[10];//准备b,c数组分别来存储依次输入的数字与运算符字符
int k=0,l=0;
int sum=0;
for(int i=0;i<strlen(temp)-1;i++)// NOT =
{
if(isdigit(temp[i]))
{
b[k++]=temp[i]-48;
}
else if(temp[i]=='#')
{
b[k-1]=b[k-1]*10+temp[i+1]-48;
i++;
}
else
{
c[l++]=temp[i];
}
}
for(int i=0;i<l;i++)
{
if(c[i]=='*')
{
b[i+1]=b[i]*b[i+1];
for(int j=i;j<l-1;j++)
c[j]=c[j+1];
for(int j=i;j<k-1;j++)
b[j]=b[j+1];
i--;
l--;
k--;
}
}
sum=b[0];
for(int i=0;i<l;i++)
{
switch(c[i])//来判断输入的运算符。
{
case '+':
sum=sum+b[i+1];
break;
case '-':
sum-=b[i+1];
break;
}
}
return sum; //输出最终结果。
}
void dfs(int d,int c)
{
if(temp[d]=='=') return;//finished
int k=strlen(temp);
temp[d]=y[c];
/*
cout<<d<<endl;
for(int i=0;i<strlen(temp);i++)
cout<<temp[i];
cout<<endl;
cout<<check(temp)<<":"<<compute(temp)<<endl;*/
if(check(temp)&&compute(temp)==NUM)
{
print(temp);
}
for(int i=0;i<4;i++)
{
dfs(d+2,i);
}
}
void process()
{
memcpy(temp,str,sizeof(char)*n);
n=strlen(str);
res.clear();
int k=0;
int i;
for(i=0;i<strlen(str)-2;i++)
{
temp[k++]=str[i];
temp[k++]='#';
}
temp[k++]=str[i++];
temp[k++]=str[i++];
for(int i=0;i<4;i++)
{
dfs(1,i);
}
cout<<"Problem "<<kase++<<endl;
if(res.size()>0)
{
set<string>::iterator it;
for(it=res.begin();it!=res.end();it++)
cout<<" "<<*it<<endl;
}else
{
cout<<" IMPOSSIBLE"<<endl;
}
}
int main()
{
do
{
gets(str);
process();
}while(!(strlen(str)==1&&str[0]=='='));
}