您的位置:首页 > 其它

[NOIP2004]虫食算 高斯消元

2014-12-02 00:07 225 查看
网上的题解各种坑 真是尴尬 搞了好久 现在弄懂了

给出样例

5
ABCED
BDACE
EBBAA

废话不多说 乱枚举肯定超时 作如下处理



D + E - A = d1

C + E - A = -d1 + d2

C + A - B = -d2 + d3

B + D - B = -d3 + d4

A + B - E = -d4 + d5

将上述表达式消元 得到下列式子(di 等于 1 (进位) 或 0 (不进位)

A = x1 * d1 + x2 * d2 + x3 * d3 + x4 * d4 + x5 * d5

B = ...

C = ...

D = ...

E = ...

可以发现x的取值与d毫无关系 所以我们只要枚举d代入上式算出各值检验时候符合要求即可 (代码中x用g数组储存 d用above储存)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXN 30
#define MAXM 64
typedef long long LL;
int T[MAXM+10][MAXN+10], g[MAXN+10][MAXN+10];
int Last[MAXN+10], litole[MAXN+10], letoli[MAXN+10];
int n, above[MAXN+10];
int Ans[MAXM+10];
char s[3][MAXN+10];
int gcd(int a, int b)
{
	while(b)
	{ int r = a % b; a = b; b = r; }
	return a;
}
template <int maxn, int maxm>
struct Maxtrix{
	int equ, var;
	int A[maxn+10][maxm+10];
	void init() { memset(A, 0, sizeof(A)); equ = var = 0; }
	void get_op(int i)
	{
		for(int j = 1; j <= var; j++) {  // '<=' ? !!!
			A[i][j] = -A[i][j];
			g[i][j] = -g[i][j];
		}
	}
	void Gauss() {            // 这里需要修改!!!!!!
		for(int row = 1; row <= equ; row++)
		{
			int Max = 0, f, col, k;
			for(col = 1; col <= var; col++)
				if(fabs(A[row][col]) > Max)
				{
					Max = fabs(A[row][col]);
					k = col;
				}
			if(!Max) continue;
			col = k;
			litole[row] = col; letoli[col] = row;
			if(A[row][col] < 0) get_op(row);
			for(int i = 1; i <= equ; i++)
			{
				if(i == row) continue;
				if(A[i][col] < 0) get_op(i);
				f = gcd(A[row][col], A[i][col]);
				for(int j = 1; j <= var; j++)
				{
					g[i][j] = g[i][j] * (A[row][col] / f) - g[row][j] * (A[i][col] / f);
					if(j == col) continue;
					A[i][j] = A[i][j] * (A[row][col] / f) - A[row][j] * (A[i][col] / f);
				}
				A[i][col] = 0;
				f = A[i][1];
				for(int j = 2; j <= var; j++)
				{
					f = gcd(f, fabs(A[i][j]));
					f = gcd(f, fabs(g[i][j]));
				}
				if(!f || f == 1) continue;
				for(int j = 1; j <= var; j++)
				{
					A[i][j] /= f;
					g[i][j] /= f;
				}
			}
		}
	}
};
Maxtrix <MAXM, MAXN> A;
bool Check()
{
	bool vis[MAXN+10]; memset(vis, 0, sizeof(vis));
	for(int i = 1; i <= A.equ; i++)
	{
		int sum = 0;
		for(int j = 2; j <= n; j++)
			sum += above[j] * g[i][j];
		if(sum % A.A[i][litole[i]] != 0) return false;
		sum /= A.A[i][litole[i]];
		if(sum > n || sum < 0) return false;
		if(vis[sum]) return false;
		vis[Ans[i] = sum] = true;
	}
	return true;
}
void DFS(int cur)
{
	if(cur > n) {
		if(!Check()) return ;
		printf("%d", Ans[letoli[1]]);
		for(int i = 2; i <= n; i++) printf(" %d", Ans[letoli[i]]);
		exit(0);
	}
	above[cur] = 0; DFS(cur+1);
	above[cur] = 1; DFS(cur+1);
}
int main()
{
	scanf("%d", &n);
	for(int i = 0; i < 3; i++) scanf("%s", s[i]);
	A.init();
	A.equ = A.var = n;
	for(int i=n-1;i>=0;i--)
	{
        T[i+1][s[0][i]-'A'+1]++;
        T[i+1][s[1][i]-'A'+1]++;
        T[i+1][s[2][i]-'A'+1]--;
        g[i+1][i+1]=n; g[i+1][i+2]=-1;
    }
	memcpy(A.A, T, sizeof(T));
	A.Gauss();
	DFS(2);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: