poj 1487 Single-Player Games 高斯消元

  • 这题虽然做的人不多,其实还是很裸的高斯消元。

题意还是很好理解的,比如对于第二个样例

2
a = (1 b)
b = (4 a)
我们可以得出 a = 0.5+0.5*b , b = 0.5*4+0.5*a,这样就可以建立方程组来解题。
预处理有点麻烦,我是对于每个区间递归处理的,代码有点搓,但还是比较好理解的。
前面由于精度问题没经验,被坑了好几次。。。还很水,希望快点强大起来!
第一次发题解~真有趣
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;

double a[33][222] , x[33];
char s[33][222];
int n ;
bool freex[33] ;
double eps = 1e-6;
void debug()
{
	int i,j;
	puts("debug");
	for(i = 0;i < n ;i++)
	{
		for(j = 0;j < n+1;j++)
			printf("%.3lf ", a[i][j]);
		puts("");
	}
	puts("end");
}
void find(int i,double d,int st,int to) 
{
	//i表示当前处理的字母  d表示前面处理出的倍数 
	int j,k;
	int num = 0 ;
	double x = 0 ; // x 当前区间有多少元素 
	for(j = st;j <= to; j++)
		if(s[i][j] == '(')
			num++;
		else if(s[i][j] == ')')
		{
			num--;
			if(num == 0)
				x = x+1;
		}
		else if(s[i][j] != ' ' && num == 0)
		{
			while(s[i][j+1] >= '0' && s[i][j+1] <= '9')
				j++;
			x = x+1;
		}
	//printf("st = %d to = %d x = %.0lf\n" , st, to, x);
	num = 0;
	int pre ;
	for(j = st;j <= to; j++)
		if(s[i][j] == '(')
		{
			if(num == 0)
				pre = j;
			num++;
		}
		else if(s[i][j] == ')' )
		{
			num--;
			if(num == 0)
				find(i , d/x , pre+1,j-1);
		}
		else if(s[i][j] != ' ' && num == 0)
		{
			if(s[i][j] == '-') // 负数的情况 
			{
				int xx = 0;
				j++;
				while(s[i][j] >= '0' && s[i][j] <= '9')
					xx = xx*10+s[i][j]-'0' , j++;
				a[i][n] += -1.0*xx*d/x;
			}
			else if(s[i][j] >= 'a' && s[i][j] <= 'z' ) //字母的情况 
				a[i][ s[i][j]-'a' ] += -1.0*d/x;
			else
			{
				int xx = 0;
				while(s[i][j] >= '0' && s[i][j] <= '9')
					xx = xx*10+s[i][j] - '0' , j++;
				a[i][n] += 1.0*xx*d/x;
			}
		}
}
void gauss()
{
	int row = 0 , col = 0 ;
	int i , j ;
	for( ; row < n && col < n; row++ , col++)
	{
		int maxr = row;
		for(i = row+1;i < n ; i++)
			if(a[i][col] != 0)
				maxr = i;
		if(fabs(a[maxr][col])<eps) // 注意精度 
		{
			row --;
			continue;
		}
		if(maxr != row)
			for(i = col;i < n +1;i ++)
				swap(a[maxr][i] , a[row][i]);
		for(i = row+1;i < n ; i++)
		{
			if(a[i][col] == 0)
				continue;
			double d = a[i][col]/a[row][col];
			for(j = col;j < n+1;j ++)
				a[i][j] = a[i][j] - a[row][j]*d;
		}
	}
//	debug();
//	printf("row = %d\n", row) ;
	if(row < n)
	{
		for(i = row-1;i >= 0; i--)
		{
			int num = 0 , id ;
			for(j = i;j < n; j++)
				if(freex[j] && !(fabs(a[i][j]) < eps) )
					num++ , id = j ;
			if(num > 1)
				continue;
			x[id] = a[i][n];
			for(j = id+1;j < n ;j ++)
				x[id] -= a[i][j]*x[j];
			x[id] /= a[i][id];
			freex[id] = 0;
		}
		for(i = 0;i < n; i++)
			if(freex[i])
				printf("Expected score for %c undefined\n", 'a'+i);
			else
				printf("Expected score for %c = %.3lf\n" , i+'a' , x[i]);
		puts("");
		return ;
	}
	for(i = n-1;i >= 0;i --)
	{
		x[i] = a[i][n];
		for(j = i+1;j < n ;j ++)
			x[i] -= x[j]*a[i][j];
		x[i] = x[i]/a[i][i];
	}
	for(i = 0;i < n; i++)
		printf("Expected score for %c = %.3lf\n" , i+'a' , x[i]);
	puts("");
}
void init()
{
	memset(a, 0, sizeof(a)) ;
	memset(freex , true , sizeof(freex)) ;
}
int main()
{
	int i,j , cas = 1;;
	while(scanf("%d", &n) != -1 && n)
	{
		getchar() ;
		init();
		for(i = 0;i < n ; i++)
			gets(s[i]) ;
		int st,to ;
		for(i = 0;i < n  ;i++)
		{
			a[i][i] = 1;
			int len = strlen(s[i]);
			for(j = 0;j < len ; j++)
				if(s[i][j] == '(')
				{
					st =j;
					break;
				}
			for(j = len-1;j >= 0; j--)
				if(s[i][j] == ')' )
				{
					to = j;
					break;
				}
			find(i,1.0,st+1,to-1);
		}
	//	debug();
		printf("Game %d\n", cas++);
		gauss();
	}
	return 0;
}


你可能感兴趣的:(poj,高斯消元)