zoukankan      html  css  js  c++  java
  • POJ 1681 Painter's Problem(高斯消元+枚举自由变元)

    http://poj.org/problem?id=1681

    题意:
    有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色。

    思路:

    这道题目也就是要处理自由变元,如果自由变元为0,那么刷法是唯一的,如果有多个自由变元,那么可以有多种刷法,需要枚举处理。

    借鉴了kuangbin大神的高斯消元模板,写得真的是好。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn = 400 + 5;
     17 
     18 int n;
     19 int equ,var;  //equ个方程,var个变元
     20 int x[maxn]; //解集
     21 int a[maxn][maxn]; //矩阵
     22 int free_x[maxn];  //存储自由变元
     23 int free_num;      //自由变元的个数
     24 
     25 //返回值为-1表示无解,为0表示唯一解,否则返回自由变元个数
     26 int Gauss()
     27 {
     28     int max_r,col,k;
     29     free_num=0;
     30     for(k=0,col=0; k<equ && col<var; k++,col++)
     31     {
     32         max_r=k;
     33         for(int i=k+1;i<equ;i++)
     34         {
     35             if(abs(a[i][col])>abs(a[max_r][col]))
     36                 max_r=i;
     37         }
     38         if(a[max_r][col]==0)
     39         {
     40             k--;
     41             free_x[free_num++]=col;  //这个是自由变元;
     42             continue;
     43         }
     44         if(max_r!=k)
     45         {
     46             for(int j=col; j<var+1; j++)
     47                 swap(a[k][j],a[max_r][j]);
     48         }
     49         for(int i=k+1;i<equ;i++)
     50         {
     51             if(a[i][col]!=0)
     52             {
     53                 for(int j=col;j<var+1;j++)
     54                     a[i][j]^=a[k][j];
     55             }
     56         }
     57     }
     58     for(int i=k;i<equ;i++)
     59         if(a[i][col]!=0)  return -1;  //无解
     60     if(k<var)  return var-k;          //有多解时返回自由变元个数
     61     //唯一解,回代
     62     for(int i=var-1; i>=0 ;i--)
     63     {
     64         x[i]=a[i][var];
     65         for(int j=i+1; j<var; j++)
     66             x[i]^=(a[i][j] && x[j]);
     67     }
     68     return 0;
     69 }
     70 
     71 void print(int t)
     72 {
     73     if(t==-1)  puts("inf");
     74     else if(t==0)
     75     {
     76         int ans=0;
     77         for(int i=0;i<n*n;i++)   ans+=x[i];
     78         printf("%d
    ",ans);
     79     }
     80     else
     81     {
     82         //枚举自由变元
     83         int ans=INF;
     84         for(int i=0;i<(1<<t);i++)
     85         {
     86             int cnt=0;
     87             for(int j=0;j<t;j++)
     88             {
     89                 if(i&(1<<j))
     90                 {
     91                     x[free_x[j]]=1;
     92                     cnt++;
     93                 }
     94                 else x[free_x[j]]=0;
     95             }
     96             for(int j=var-t-1;j>=0;j--)
     97             {
     98                 int idx;
     99                 for(idx=j; idx<var; idx++)
    100                     if(a[j][idx])  break;
    101                 x[idx]=a[j][var];
    102                 for(int l=idx+1; l<var; l++)
    103                     if(a[j][l])  x[idx]^=x[l];
    104                 cnt+=x[idx];
    105             }
    106             ans=min(ans,cnt);
    107         }
    108         printf("%d
    ",ans);
    109     }
    110 }
    111 
    112 int main()
    113 {
    114     //freopen("in.txt","r",stdin);
    115     int T;
    116     scanf("%d",&T);
    117     while(T--)
    118     {
    119         scanf("%d",&n);
    120         memset(a,0,sizeof(a));
    121 
    122         for(int i=0;i<n*n;i++)
    123         {
    124             a[i][i]=1;
    125             if(i/n)      a[i-n][i]=1;
    126             if(i/n<n-1)  a[i+n][i]=1;
    127             if(i%n)      a[i-1][i]=1;
    128             if(i%n<n-1)  a[i+1][i]=1;
    129         }
    130 
    131         char s[20];
    132         for(int i=0;i<n;i++)
    133         {
    134             scanf("%s",s);
    135             for(int j=0;j<n;j++)
    136             {
    137                 if(s[j]=='y')  a[i*n+j][n*n]=0;
    138                 else a[i*n+j][n*n]=1;
    139             }
    140         }
    141 
    142         memset(x,0,sizeof(x));
    143         equ=var=n*n;
    144         print(Gauss());
    145     }
    146     return 0;
    147 }
  • 相关阅读:
    使用yum命令报错
    CentOS6.8安装Python3.6.3
    解决 linux 下安装 node 报: command not found
    Python的pip源切换为国内阿里云镜像
    开源Java加密工具Jasypt 1.4发布
    JavaFX对Java开发者到底意味着什么?
    16 个印象深刻的 HTML5/CSS3/JavaScript 体验
    高效的Java异常处理
    Java开发的学习过历程
    Java中23种设计模式详解
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7277923.html
Copyright © 2011-2022 走看看