Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

这个题目用C++对象来求解还是比较方便的,用C写的递归都把人写烦了,79ms

Posted by hujk2008 at 2012-09-16 11:43:57 on Problem 1100 and last updated at 2012-09-16 12:46:46
In 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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator