| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
这个题目用C++对象来求解还是比较方便的,用C写的递归都把人写烦了,79msIn Reply To:Re:36小时,终于搞定了这个问题 Posted by:closure at 2011-09-23 12:26:20 简单封装一下表达式语句对象,然后输入的时候递归生成语义树,处理时方便多了。
#include <stdio.h>
#include <string.h>
#define MAXLEN 20
typedef struct st_expression expression ;
typedef struct st_metadata metadata;
// 子元素,既可以是整数,也是一个语句
char g_sigchange[]={'+','-','*'};
struct st_metadata
{
int nType ;
int n ;
expression *e ;
st_metadata()
{
nType = n = 0 ;
e = NULL ;
}
};
struct st_expression
{
int nLen ;
metadata Op[MAXLEN] ;
char csigh[MAXLEN];
st_expression(){nLen = 0;}
~st_expression()
{
int i ;
for (i = 0 ;i < nLen; i ++)
{
if( Op[i].nType == 1 && Op[i].e != NULL)
{
delete Op[i].e ;
Op[i].e = NULL ;
}
}
};
int getOpCount() {
int i ,nCount = 0;
for( i = 0 ;i < nLen; i ++ )
{
if( Op[i].nType == 1)
nCount += Op[i].e->getOpCount() ;
else
nCount ++ ;
}
return nCount ;
} ;
int Caculate(char sigh[], int &singindex)
{
int nRes = 0 , i ;
if( nLen <= 0 )
return 0 ;
nRes = Op[0].nType == 0?Op[0].n:Op[0].e->Caculate(sigh,singindex) ;
for( i = 1 ;i < nLen ;i ++ )
{
switch(csigh[i-1] = sigh[singindex++])
{
case 0:
nRes += (Op[i].nType == 0?Op[i].n:Op[i].e->Caculate(sigh,singindex) );
break ;
case 1:
nRes -= (Op[i].nType == 0?Op[i].n:Op[i].e->Caculate(sigh,singindex) );
break ;
case 2:
nRes *= (Op[i].nType == 0?Op[i].n:Op[i].e->Caculate(sigh,singindex) );
break ;
}
}
return nRes ;
}
void print( int nlevel)
{
int i ;
if( nlevel > 0)
printf("(") ;
for( i = 0; i < nLen; i ++ )
{
if( Op[i].nType == 0)
printf("%d",Op[i].n) ;
else
{
Op[i].e->print(nlevel + 1) ;
}
if( i != nLen - 1)
printf("%c",g_sigchange[csigh[i]]) ;
}
if( nlevel > 0)
printf(")") ;
}
};
class CDreisamEquations
{
public:
CDreisamEquations(){m_nCount=1 ;m_exp=NULL ;}
int Input() ;
void Reset() ;
int IsNum(char ch ){ return ch >='0' && ch <= '9';};
int Parse(char * str,expression * e);
int solve() ;
void print() ;
public:
expression * m_exp ;
int m_nSum ;
int m_nCount ;
int m_bFind ;
int m_SignCount ;
};
void CDreisamEquations::Reset()
{
if( NULL != m_exp)
{
delete m_exp ;
m_exp = NULL ;
}
m_bFind = 0 ;
}
int CDreisamEquations::Input()
{
int i , nCount = 0 ;
char buffer[100];
Reset() ;
m_exp = new expression() ;
m_nSum = 0 ;
buffer[0] = getchar() ;
if( buffer[0] == '0')
return 0 ;
nCount = 1 ;
do
{
buffer[nCount++] = getchar() ;
} while (buffer[nCount-1] != '\n');
if( buffer[nCount-2] == '\r')
nCount -- ;
buffer[--nCount] = '\0' ;
for( i = 0 ;i < nCount ; i ++)
{
if( IsNum(buffer[i]))
m_nSum = m_nSum * 10 + buffer[i] - '0';
else if( buffer[i] == '=')
break;
}
Parse(buffer+i+1,m_exp) ;
return 1 ;
}
int CDreisamEquations::Parse(char * str,expression * e)
{
int i , nlen , start = 0;
nlen = strlen(str) ;
i = 0 ;
// 忽略空格
while(str[i]==' ' && i < nlen) i ++ ;
for( ;i < nlen ;i ++ )
{
if( i >= nlen)
break ;
if( IsNum(str[i]))
{
e->Op[e->nLen].n = e->Op[e->nLen].n * 10 + str[i] - '0' ;
start = 1 ;
}else if( str[i] == ' ')
{
if( start == 1)
{
e->nLen ++ ;
start = 0 ;
}
}
else if( str[i] == '(')
{
if( start == 1)
{
e->nLen ++ ;
start = 0 ;
}
e->Op[e->nLen].nType = 1 ;
e->Op[e->nLen].e = new expression() ;
i += (1 + Parse(str+i+1,e->Op[e->nLen].e));
e->nLen ++;
}else if( str[i] == ')')
{
break ;
}
}
if( start == 1)
{
e->nLen ++ ;
}
return i ;
}
int CDreisamEquations::solve()
{
int j,sighindex;
char sigh[50] ;
m_SignCount = m_exp->getOpCount() - 1;;
memset(sigh,0,sizeof(sigh)) ;
sighindex = 0 ;
if( m_SignCount < 0)
return 0 ;
if( m_SignCount == 0)
{
if( m_exp->Caculate(sigh,sighindex) == m_nSum)
return m_bFind = 1;
}
#if 1 // 暴力枚举两种方法
while(1)
{
sighindex = 0 ;
if( m_exp->Caculate(sigh,sighindex) == m_nSum)
return m_bFind = 1;
if( m_SignCount <= 0 )
break ;
sigh[m_SignCount - 1] ++ ;
for( j = m_SignCount - 1 ; j >= 0 ; j -- )
{
if( sigh[0] >= 3)
{
return 0 ;
}
else if( sigh[j] >= 3)
{
sigh[j] = 0 ;
sigh[j-1] ++ ;
}else
break ;
}
}
#else
int i , tmp ,v;
v = VPow(3,m_SignCount) ;
for( i = 0 ;i < v &&!m_bFind ;i ++ )
{
tmp = i ;
for( j = m_SignCount - 1; j >= 0 ; j --)
{
if( tmp == 0)
{
sigh[j] = 0 ;
continue;
}
sigh[j] = tmp % 3 ;
tmp /= 3 ;
}
sighindex = 0 ;
if( m_exp->Caculate(sigh,sighindex) == m_nSum)
return m_bFind = 1;
}
#endif
return 0 ;
}
void CDreisamEquations::print()
{
printf("Equation #%d:\n",m_nCount++) ;
if( !m_bFind)
{
printf("Impossible\n\n") ;
return ;
}
printf("%d=",m_nSum) ;
m_exp->print(0) ;
printf("\n\n");
}
int main( )
{
CDreisamEquations s ;
while(s.Input())
{
s.solve();
s.print() ;
}
return 0 ;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator