POJ 1830 开关问题

来源:互联网 发布:修复微信闪退的软件 编辑:程序博客网 时间:2024/06/10 13:05

高斯消元。

开关问题类型的模板题。

分析:写成n*n的矩阵,注意初始状态和最终状态。
初始状态 到 最终状态  等同于   全零状态  到 (最终状态异或初始状态)。将可以影响该位置变换的位置(自己,上,下,左,右)置1,其余的置0。注意变换的顺序。

代码:

#include <iostream>#include <algorithm>#include <string>#include <cstring>#include <cstdio>#include <cmath>using namespace std;const int MAXN = 50; //未知数数目int equ, var;        //equ个方程,var个变元int a[MAXN][MAXN];   //行数为equ,0~var列为系数,var列为得数int x[MAXN];         //解集int free_num;        //自由变元数量int free_x[MAXN];    //自由变元,多解枚举时会用到/********************************************************               mod2高斯消元过程*       返回-1无解,0惟一解,>0自由变元数目*******************************************************/int Gauss(){    int maxr, col, i, j, k;    free_num = 0;    for (k = 0, col = 0; k<equ && col<var; k++, col++)    {        maxr = k;        for (i = k + 1; i<equ; i++)        {            if (abs(a[i][col])>abs(a[maxr][col]))                maxr = i;        }        if (a[maxr][col] == 0)        {            k--;            free_x[free_num++] = col;                 //出现一个自由变元            continue;        }        if (maxr != k)        {            for (j = col; j<var + 1; j++)                swap(a[k][j], a[maxr][j]);        }        for (i = k + 1; i<equ; i++)        {            if (a[i][col] != 0)            {                for (j = col; j<var + 1; j++)                    a[i][j] ^= a[k][j];            }        }    }    for (i = k; i<equ; i++)        if (a[i][col] != 0)            return -1;              //无解情况    if (k<var)        return var - k;             //多个自由变元    for (i = var - 1; i >= 0; i--)  //惟一解,进行回代    {        x[i] = a[i][var];        for (j = i + 1; j<var; j++)            x[i] ^= (a[i][j] && x[j]);    }    return 0;}void work(int n){    int i, j, k, t;    int inital_sate[MAXN], target_state[MAXN];    memset(a, 0, sizeof(a));    memset(x, 0, sizeof(x));    equ = n;    var = n;    for (i = 0; i < n; i++)        scanf("%d", &inital_sate[i]);    for (i = 0; i < n; i++)        scanf("%d", &target_state[i]);    for (i = 0; i < n; i++)    {        a[i][i] = 1;        a[i][n] = inital_sate[i] ^ target_state[i];    }    int x, y;    while(cin >> x >> y && x+y)    {        a[y-1][x-1] = 1;    }    int ans = Gauss();    if (ans == -1)        printf("Oh,it's impossible~!!\n");    else        printf("%d\n",(1<<ans));}int main(){    int i, T;    scanf("%d", &T);    for (i = 1; i <= T; i++)    {        int n;        cin >> n;        work(n);    }    return 0;}



原创粉丝点击