zoj1022 Parallel Expectations(DP)

/*
 这道题算不上难题,不过算得上的麻烦题了。
 设状态 T[ i ][ j ] 为程序1执行i条指令,程序2执行j条指令后的变量平均值,P1为程序1指令i的概率,P2为程序2指令j的概率
  则容易推出,T[ i ][ j ] = (T[ i-1 ][ j ]*P1+T[ i ][ j-1 ]*P2)/(P1+P2) 不过需要注意几点:
 1.理解题意很重要,这个题很容易误解 。
  如果认为每种指令执行的情况是一样的话,就会求错方程:(设N[ i ][ j ]为状态T[ i ][ j ]数量 )
    P1 = N[ i-1 ][ j ]/N[ i ][ j ]
    P2 = N[ i ][ j-1 ]/N[ i ][ j ]
  下面是POJ discuss 离得解释,看了这个就会明白了。
  Example :
   Exactly one execution of the sample input results in S=8, and the
   probability of that execution is not 1/C(8,4)=1/70, but (1/2)^4=1/16,
   since the program automatically execute remaining operations.
   It is true that there are 70 different executions, but not all of
   them have the same probability.
   正确的概率计算为:(设N1为程序1指令总条数,N2为程序2指令总条数 )
    if ( i == N1 && j == N2 ) P1 = P[ i-1 ][ j ]  ,P2 = P[ i ][ j-1 ]
    if ( i  < N1 && j == N2 ) P1 = P[ i-1 ][ j ]  ,P2 = P[ i ][ j-1 ]/2
    if ( i == N1 && j  < N2 ) P1 = P[ i-1 ][ j ]/2,P2 = P[ i ][ j-1 ]
    if ( i  < N1 && j  < N2 ) P1 = P[ i-1 ][ j ]/2,P2 = P[ i ][ j-1 ]/2
    P[ i ][ j ] = P1 + P2
   (囧,把P[ i-1 ][ j ]当成P1,P[ i ][ j-1 ]当成P2,WA了N次,关键是测试样例都没过,不过这题的数据有点弱的说,
  样例一过,题马上就过了。)
 2.实现起来有点麻烦,要是比赛,只能无题可做时才会做吧,因为这类似个小型的编译器了。
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))

char Command[ 2 ][ 26 ][ 65 ];

struct asmmble {
	int  Varible1;
	int  Varible2;
	char Operator;
}Asmmble[ 2 ][ 105 ];

int Read( char Command[][ 65 ] )
{
	int  List 	= 0;
	char ch		= 0;
	while ( 1 ) {
		int  Count  = 0;
		while ( ( ch = getchar() ) != '\n' ) {
			while ( ch == ' ' ) ch = getchar();
			Command[ List ][ Count ++ ] = ch;
		}
		Command[ List ][ Count ] = '\0';
		if ( !strcmp( Command[ List ], "END" ) ) break;
		if ( strcmp( Command[ List ], "" ) ) ++ List;
	}
	return List;
}

struct word {
	int Start;
	int End;
}Word[ 3 ];

struct varible {
	char 	Name[ 21 ];
	int 	Length;
	double	Value;
	bool    IsConst;
}Varible[ 155 ];

int Search( int& Number, char* String, int number )
{
	for ( int i = 4 ; i < Number ; ++ i )
		if ( Varible[ i ].Length == number && !strcmp( Varible[ i ].Name, String ) )
			return i;
	strcpy( Varible[ Number ].Name, String );
	Varible[ Number ].Length  = number;
	Varible[ Number ].IsConst = false;
	Varible[ Number ].Value	  = 0.0;
	return Number ++;
}

char Change( char ch )
{
	if ( ch >= 'a' && ch <= 'z' )
		return ch - 'a' + 'A';
	return ch;
}

int searchVarible( char* Command, word Word, int& Number )
{
	int  count = 0;
	char String[ 21 ];
	if ( Command[ Word.Start ] >= '0' && Command[ Word.Start ] <= '9' ) {
		count = Command[ Word.Start ++ ]-'0';
		while ( Word.Start <= Word.End ) {
			count *= 10;
			count += Command[ Word.Start ++ ]-'0';
		}
		strcpy( Varible[ Number ].Name, "0");
		Varible[ Number ].Length	= 1;
		Varible[ Number ].IsConst 	= true;
		Varible[ Number ].Value		= count;
		return Number ++;
	}else {
		int number = 0;
		String[ number ++ ] = Change( Command[ Word.Start ++ ] );
		while ( Word.Start <= Word.End ) 
			String[ number ++ ] = Change( Command[ Word.Start ++ ] );
		String[ number ] = '\0';
		return Search( Number, String, number );
	}
}

void commbine( int m, int n, int v1, int v2 ,char o3 )
{
	Asmmble[ m ][ n ].Varible1 = v1;
	Asmmble[ m ][ n ].Varible2 = v2;
	Asmmble[ m ][ n ].Operator = o3;
}

void Operat( int n, int m, int XX, int YY, int ZZ, char O )
{
	int R1 = 2*m+0;
	int R2 = 2*m+1;
	commbine( m, 4*n+1, R1, YY, ':' );
	commbine( m, 4*n+2, R2, ZZ, ':' );
	commbine( m, 4*n+3, R1, R2,  O  );
	commbine( m, 4*n+4, XX, R1, ':' );
}

int FindChar( char* p, char O )
{
	int count = 0;
	while ( p[ count ] ) {
		if ( p[ count ] == O )
			return count;
		++ count;
	}
	return -1;
}

int command( int machine, char Command[][ 65 ], int List, int Number )
{
	for ( int i = 0 ; i < List ; ++ i ) {
		int space1 = FindChar( Command[ i ], ':' );
		int space2 = max( FindChar( Command[ i ], '+' ), FindChar( Command[ i ], '-' ) );
		int space3 = strlen( Command[ i ] );
		Word[ 0 ].Start = 0;		Word[ 0 ].End = space1-1;
		Word[ 1 ].Start = space1+2; Word[ 1 ].End = space2-1;
		Word[ 2 ].Start = space2+1; Word[ 2 ].End = space3-1;
		
		int X = searchVarible( Command[ i ], Word[ 0 ], Number );
		int Y = searchVarible( Command[ i ], Word[ 1 ], Number );
		int Z = searchVarible( Command[ i ], Word[ 2 ], Number );
		
		Operat( i, machine, X, Y, Z, Command[ i ][ space2 ] );
	}
	return Number;
}

void calculate( double* Var, asmmble Asm )
{
	switch( Asm.Operator ) {
		case ':':	Var[ Asm.Varible1 ]  = Var[ Asm.Varible2 ];break;
		case '+':	Var[ Asm.Varible1 ] += Var[ Asm.Varible2 ];break;
		case '-':	Var[ Asm.Varible1 ] -= Var[ Asm.Varible2 ];break;
	}
}

int cmpstr( char* a, char* b, int n )
{
	for ( int i = 0 ; i < n ; ++ i )
		if ( a[ i ] != b[ i ] )
			return a[ i ] - b[ i ];
	return 0;
}

int cmp( const void* a, const void* b )
{
	struct varible* p = (struct varible*)a;
	struct varible* q = (struct varible*)b;
	if ( p->IsConst == q->IsConst ) {
		int value = cmpstr( p->Name, q->Name, min( p->Length, q->Length ) );
		if ( !value )
			return p->Length - q->Length;
		else return value;
	}else return q->IsConst - p->IsConst;
}

double M1[ 55 ],M2[ 55 ];
double P[ 105 ][ 105 ],P1,P2;
double T[ 101 ][ 101 ][ 35 ];

void dp( int number1, int number2, int count )
{
	P[ 0 ][ 0 ] = 1.0;
	
	for ( int k = 0 ; k < count ; ++ k )
		if ( Varible[ k ].IsConst )
			T[ 0 ][ 0 ][ k ] = Varible[ k ].Value+0.0;
		else
			T[ 0 ][ 0 ][ k ] = 0.0;
			
	for ( int i = 1 ; i <= number1 ; ++ i ) {
		P[ i ][ 0 ] = 0.5*P[ i-1 ][ 0 ];
		for ( int k = 0 ; k < count ; ++ k ) 
			T[ i ][ 0 ][ k ] = T[ i-1 ][ 0 ][ k ];
		calculate( T[ i ][ 0 ], Asmmble[ 0 ][ i ] );
	}
	
	for ( int j = 1 ; j <= number2 ; ++ j ) {
		P[ 0 ][ j ] = 0.5*P[ 0 ][ j-1 ];
		for ( int k = 0 ; k < count ; ++ k ) 
			T[ 0 ][ j ][ k ] = T[ 0 ][ j-1 ][ k ];
		calculate( T[ 0 ][ j ], Asmmble[ 1 ][ j ] );
	}
	
	for ( int i = 1 ; i <= number1 ; ++ i )
	for ( int j = 1 ; j <= number2 ; ++ j ) {
		for ( int k = 0 ; k < count ; ++ k ) {
			M1[ k ] = T[ i-1 ][ j ][ k ];
			M2[ k ] = T[ i ][ j-1 ][ k ];
		}
		calculate( M1, Asmmble[ 0 ][ i ] );
		calculate( M2, Asmmble[ 1 ][ j ] );
		
		if ( i < number1 && j < number2 ) {
			P1 = P[ i-1 ][ j ]/2;P2 = P[ i ][ j-1 ]/2;
		}else if ( i < number1 ) {
			P1 = P[ i-1 ][ j ];  P2 = P[ i ][ j-1 ]/2;
		}else if ( j < number2 ) {
			P1 = P[ i-1 ][ j ]/2;P2 = P[ i ][ j-1 ];
		}else {
			P1 = P[ i-1 ][ j ]  ;P2 = P[ i ][ j-1 ];
		}
		P[ i ][ j ] = P1 + P2;
		//用 P[ i-1 ][ j ],P[ i ][ j-1 ] 代替 P1,P2的值了。。。 
		for ( int k = 0 ; k < count ; ++ k )
			T[ i ][ j ][ k ] = (P1*M1[ k ]+P2*M2[ k ])/(P[ i ][ j ]);
	}
	
	for ( int k = 0 ; k < count ; ++ k )
		Varible[ k ].Value = T[ number1 ][ number2 ][ k ];
	
	qsort( &Varible[ 4 ], count-4, sizeof( Varible[ 0 ] ), cmp );
	
	int start = 4;
	while ( Varible[ start ].IsConst ) ++ start;
	for ( int i = start ; i < count ; ++ i )
		printf("%.4lf\n",Varible[ i ].Value);
}

void Initial( void )
{
	for ( int k = 0 ; k < 4 ; ++ k ) {
		Varible[ k ].IsConst = false;
		Varible[ k ].Value 	 = 0.0;
	}
}

int main()
{
	int t,line1,line2,numb1,numb2;
	while ( scanf("%d",&t) != EOF )
	while ( t -- ) {
		Initial();
		
		line1 = Read( Command[ 0 ] );
		line2 = Read( Command[ 1 ] );
		
		numb1 = command( 0, Command[ 0 ], line1, 00004 );
		numb2 = command( 1, Command[ 1 ], line2, numb1 );
		
		dp( 4*line1, 4*line2, numb2 );
		if ( t ) printf("\n");
	}
	return 0;
}

转载于:https://www.cnblogs.com/-xiaobai-/archive/2011/08/18/2143921.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值