• POJ 1222 extended lights out 高斯消元 板子题


      题目链接:http://poj.org/problem?id=1222

      题目描述:其实就是开关问题, 按下按钮会影响当前和周围的四个按钮, 问关闭所有灯的方案

      解题思路:以前用搜索做过, 那时候是刚刚接触ACM的时候, 当时劲头真足啊, 这个解释的很好:http://blog.csdn.net/u013508213/article/details/47263183

      代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 100 + 10;
    int a[maxn][maxn]; // 增广矩阵
    int x[maxn]; // 解集
    bool freeX[maxn]; // 标记是否有自由变元
    
    //高斯消元解方程组
    //返回值-2表示有浮点数解, 无整数解
    //返回值-1表示无解, 0表示唯一解, 大于0表示有无穷解,返回自由变元个数
    //有equ个方程, var个变元
    //增广矩阵函数[0, equ-1]
    //增广矩阵列数[0, var]
    int gauss(int equ, int var) {
        for( int i = 0; i <= var; i++ ) {
            x[i] = 0;
            freeX[i] = true;
        }
        //转换为阶梯矩阵
        //col表示当前正在处理的这一列
        int col = 0;
        int row = 0;
        //maxR表示当前这个列中元素绝对值最大的行
        int maxRow;
        for( ; row < equ && col < var; row++, col++ ) {
            //枚举当前正在处理的行
            //找到该col列元素绝对值最大的那行与第k行交换
            maxRow = row;
            for( int i = row + 1; i < equ; i++ ) {
                if( abs(a[maxRow][col]) < abs(a[i][col])) {
                    maxRow = i;
                }
            }
            if( maxRow != row ) {
                //与第row行交换
                for( int j = row; j < var + 1; j++ ) {
                    swap(a[row][j], a[maxRow][j]);
                }
            }
            if( a[row][col] == 0 ) {
                row--;
                continue;
            }
            for( int i = row + 1; i < equ; i++ ) {
                //枚举要删的行
                if( a[i][col] != 0 ) {
                    for( int j = col; j < var + 1; j++ ) {
                        a[i][j] ^= a[row][j];
                    }
                }
            }
        }
        for( int i = var - 1; i >= 0; i-- ) {
            x[i] = a[i][var];
            for( int j = i + 1; j < var; j++ ) {
                x[i] ^= (a[i][j] && x[j]);
            }
        }
        return 0;
    }
    int main() {
        int ncase;
        int ca = 1;
        scanf("%d", &ncase);
        while (ncase--)
        {
            memset(a, 0, sizeof(a));
            for (int i = 0; i < 30; i++)
            {
                scanf("%d", &a[i][30]);
            }
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    int t = i * 6 + j;
                    a[t][t] = 1;
                    if(i>0)a[(i-1)*6+j][t]=1;
                    if(i<4)a[(i+1)*6+j][t]=1;
                    if(j>0)a[i*6+j-1][t]=1;
                    if(j<5)a[i*6+j+1][t]=1;
                }
            }
            gauss(30, 30);
            printf("PUZZLE #%d\n", ca++);
            for(int i = 0; i < 30; i++)
            {
                printf("%d", x[i]);
                if((i+1) % 6 == 0)
                    printf("\n");
                else
                    printf(" ");
            }
        }
        return 0;
    }
    View Code

      思考:需要熟知原理, 多见题, 嗯。

  • 相关阅读:
    [bzoj5285][Hnoi2018]寻宝游戏【复杂度分析】
    2020-2021-1 20201229《信息安全专业导论》第十二周学习总结
    2020-2021-1 20201229《信息安全专业导论》第十一周学习总结
    2020-2021-1 20201229《信息安全专业导论》第十周学习总结
    2020-2021-1 20201229 《信息安全专业导论》第九周学习总结
    熟悉编程语言
    2020-2021-1 20201229 《信息安全专业导论》第八周学习总结
    如何学好编程
    2020-2021-1 20201229 《信息安全专业导论》 第七周学习总结
    实现进制转化伪代码
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/6828253.html
Copyright © 2020-2023  润新知