zoukankan      html  css  js  c++  java
  • poj1753(高斯消元解mod2方程组)

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

    题意:一个 4*4 的棋盘,初始时上面放满了黑色或白色的棋子.对 (i, j) 位置进行一次操作后 (i, j), (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1) 位置的棋子会变成原来相反的状态.问最少需要多少步可以将棋盘上的棋子全部变成白色或者黑色.

    思路:分别将棋子变成黑色和白色,然后再用高斯消元解,其中步数较小者即为答案.

    注意不存在唯一解时需要枚举自由变元来取得最小步数.

    代码:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <algorithm>
      4 #include <string.h>
      5 using namespace std;
      6 
      7 const int inf = 1e9;
      8 const int MAXN = 3e2;
      9 int equ, var;//有equ个方程,var个变元,增广矩正行数为equ,列数为var+1,从0开始计数
     10 int a[MAXN][MAXN];//增广矩正
     11 int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
     12 int free_num;//自由变元个数
     13 int x[MAXN];//解集
     14 
     15 int Gauss(void){//返回-1表示无解,0表示有唯一解,否则返回自由变元个数
     16     int max_r, col, k;
     17     free_num = 0;
     18     for(k = 0, col = 0; k < equ && col < var; k++, col++){
     19         max_r = k;
     20         for(int i = k + 1; i < equ; i++){
     21             if(abs(a[i][col] > abs(a[max_r][col]))) max_r = i;
     22         }
     23         if(a[max_r][col] == 0){
     24             k--;
     25             free_x[free_num++] = col;//这个是变元
     26             continue;
     27         }
     28         if(max_r != k){
     29             for(int j = col; j < var + 1; j++){
     30                 swap(a[k][j], a[max_r][j]);
     31             }
     32         }
     33         for(int i = k + 1; i < equ; i++){
     34             if(a[i][col] != 0){
     35                 for(int j = col; j < var + 1; j++){
     36                     a[i][j] ^= a[k][j];
     37                 }
     38             }
     39         }
     40     }
     41     for(int i = k; i < equ; i++){
     42         if(a[i][col] != 0) return -1;//无解
     43     }
     44     if(k < var) return var - k;//返回自由变元个数
     45     for(int i = var - 1; i >= 0; i--){
     46         x[i] = a[i][var];
     47         for(int j = i + 1; j < var; j++){
     48             x[i] ^= (a[i][j] && x[j]);
     49         }
     50     }
     51     return 0;
     52 }
     53 
     54 const int n = 4;
     55 string s[5];
     56 
     57 int solve(void){
     58     int op = Gauss();
     59     if(op == -1) return inf;//无解
     60     else if(op == 0){//存在唯一解
     61         int sol = 0;
     62         for(int i = 0; i < var; i++){
     63             sol += x[i];
     64         }
     65         return sol;
     66     }else{//存在多解,需要枚举自由变元找到最小需要的操作数
     67         int sol = inf;
     68         int tot = 1 << op;//有op个变元,每个变元可取0或1,共有1<<op总情况
     69         for(int i = 0; i < tot; i++){//二进制枚举,i二进制位上为1的取1,为0的取0
     70             int cnt = 0;
     71             for(int j = 0; j < op; j++){
     72                 if(i & (1 << j)){//当前第j位变元取1
     73                     x[free_x[j]] = 1;
     74                     cnt++;
     75                 }else x[free_x[j]] = 0;
     76             }
     77             for(int j = var - op - 1; j >= 0; j--){
     78                 int idx;
     79                 for(idx = j; idx < var; idx++){
     80                     if(a[j][idx]) break;
     81                 }
     82                 x[idx] = a[j][var];
     83                 for(int l = idx + 1; l < var; l++){
     84                     if(a[j][l]) x[idx] ^= x[l];
     85                 }
     86                 cnt += x[idx];
     87             }
     88             sol = min(sol, cnt);
     89         }
     90         return sol;
     91     }
     92 }
     93 
     94 void f(int op){
     95     for(int i = 0; i < n; i++){
     96         for(int j = 0; j < n; j++){
     97             int cnt = i * n + j;
     98             if(s[i][j] == 'w') a[cnt][var] = 1 - op;
     99             else a[cnt][var] = op;
    100             x[cnt] = 0;
    101         }
    102     }
    103     for(int i = 0; i < equ; i++){//构造增广矩阵
    104         int x1 = i / n;
    105         int y1 = i % n;
    106         for(int j = 0; j < var; j++){
    107             int x2 = j / n;
    108             int y2 = j % n;
    109             if(abs(x1 - x2) + abs(y1 - y2) < 2) a[j][i] = 1;
    110             else a[j][i] = 0;
    111         }
    112     }
    113 }
    114 
    115 void gel(void){
    116     int sol = inf;
    117     f(0);
    118     sol = min(sol, solve());
    119     f(1);
    120     sol = min(sol, solve());
    121     if(sol == inf) cout << "Impossible" << endl;
    122     else cout << sol << endl;
    123 }
    124 
    125 int main(void){
    126     while(cin >> s[0]){
    127         equ = var = n * n;
    128         for(int i = 1; i < n; i++){
    129             cin >> s[i];
    130         }
    131         gel();
    132     }
    133     return 0;
    134 }
    View Code
  • 相关阅读:
    自己搭建一个vue项目
    nodejs 后台开发入门
    bootstrap table入门例子
    datatable入门
    猜数字案例
    Cookie
    管理系统案例
    PHP操作数据库(以MySQL为例)
    数据库(以MySQL为例)
    案例:音乐列表
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7588907.html
Copyright © 2011-2022 走看看