首页 > 代码库 > POJ1830开关问题——gauss消元

POJ1830开关问题——gauss消元

题目链接

  • 分析:
    第一个高斯消元题目,操作是异或。奇偶可以用0、1来表示,也就表示成bool类型的方程,操作是异或,和加法没有区别
    题目中有两个未知量:每个开关被按下的次数(0、1)、每个开关的转换次数。题目只和操作次数的奇偶有关,所以用0、1表示之后,对于每个开关的转换次数就已经知道了,所以只有一个未知量,可以线性表示。练习使用模板

const int maxn = 40;
const double PI = acos(-1.0);

int a[maxn][maxn];
int gauss(int N, int M)  
{    
    int r, c, pvt;    
    bool flag;  
    for (r = 0, c = 0; r < N && c < M; ++ r, ++ c) {  
        flag = false;  
        for (int i = r; i < N; ++ i)    
            if (a[i][c]) {  
                flag = a[pvt=i][c];  
                break;  
            }  
        if (!flag) {    
            r--; continue;    
        }    
        if (pvt != r)    
            for (int j = r; j <= M; ++j) swap(a[r][j], a[pvt][j]);    
        for (int i = r+1; i < N; ++i)    
            if(a[i][c])  
            {  
                a[i][c] = false;   
                for (int j = c+1; j <= M; ++j) {    
                    if(a[r][j]) a[i][j] = !a[i][j];  
            }  
        }  
    }   
	for (int i = r; i < N; ++i)    
		if (a[i][M]) return -1;    
	if (r < M) return M-r;    
	for (int i = M-1; i >= 0; --i)
	{
		for (int j = i+1; j < M; ++j)    
			a[i][M] ^= a[j][M]*a[i][j]; 
		a[i][M] ^= a[i][i];    
	}
	return 0; 
}

int main()
{
	//    freopen("in.txt", "r", stdin);
	int T, n, x, y;
	RI(T);
	FE(kase, 1, T)
	{
		RI(n);
		CLR(a, 0);
		REP(i, n) RI(a[i][n]);
		REP(i, n)
		{
			int t;
			RI(t);
			a[i][n] ^= t;
			a[i][i] = 1;
		}
		while (RII(x, y) && x)
		{
			a[y - 1][x - 1] = 1;
		}
		int ans = gauss(n, n);
		if (ans == -1)
			puts("Oh,it‘s impossible~!!");
		else
			WI(1 << ans);
	}
	return 0;
}