Poj--1753(数学,高斯消元 + 枚举 or 暴力乱搞)

2014-09-18 00:25:47

思路:这题可以用二进制状态压缩来DFS暴力搞,由于最近在学高斯消元,就用用了。由于这题要求最小步骤,所以在有自由变元时要枚举自由变元,其他的与1222差不多。

借鉴了kuangbin的博客。敲完这题,对高斯消元、自由变元又有了更深的理解。

  1 /*************************************************************************
  2     > File Name: 1753.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Wed 17 Sep 2014 09:41:16 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <queue>
 14 #include <iostream>
 15 #include <algorithm>
 16 using namespace std;
 17 typedef long long ll;
 18 const int INF = 1 << 29;
 19 typedef int Matrix[20][20];
 20 
 21 char g[10][10];
 22 Matrix A;
 23 
 24 void Init(){
 25     memset(A,0,sizeof(A));
 26     for(int i = 0; i < 16; ++i){
 27         A[i][i] = 1;
 28         if(i >= 4) A[i][i - 4] = 1; //up
 29         if(i + 4 < 16) A[i][i + 4] = 1; //down
 30         if(i % 4 != 0) A[i][i - 1] = 1; //left
 31         if((i + 1) % 4 != 0) A[i][i + 1] = 1; //right
 32     }
 33 }
 34 
 35 int Gauss(){
 36     int pfx[20],x[20],num = 0;
 37     for(int i = 0; i < 20; ++i) pfx[i] = x[i] = 0;
 38     int equ,var; equ = var = 16;
 39     int i,j,k,r,col = 0;
 40     for(i = 0; i < equ && col < var; ++i,++col){
 41         r = i;
 42         for(j = i + 1; j < equ; ++j) if(A[j][col]){
 43             r = j;
 44             break;
 45         }
 46         if(r != i)
 47             for(j = col; j <= var; ++j) swap(A[i][j],A[r][j]);
 48         if(A[i][col] == 0){
 49             --i;
 50             pfx[num++] = col;
 51             continue;
 52         }
 53         for(k = i + 1; k < equ; ++k)
 54             if(A[k][col]){
 55                 for(j = 0; j <= var; ++j) A[k][j] ^= A[i][j];
 56             }
 57         //Debug();
 58     }
 59     for(k = i; k < equ; ++k)
 60         if(A[k][col] != 0)
 61             return -1;
 62     int ra = 1 << num,res = INF;
 63     for(k = 0; k < ra; ++k){
 64         int cnt = 0,pos = k;
 65         for(j = 0; j < num; ++j){
 66             x[pfx[j]] = (pos & 1);
 67             if(x[pfx[j]]) ++cnt;
 68             pos >>= 1;
 69         }
 70         for(j = i - 1; j >= 0; --j){
 71             int tmp = A[j][var];
 72             for(int q = j + 1; q < var; ++q)
 73                 if(A[j][q]) tmp ^= x[q];
 74             x[j] = tmp;
 75             if(x[j]) ++cnt;
 76         }
 77         if(cnt < res) res = cnt;
 78     }
 79     return res;
 80 }
 81 
 82 int main(){
 83     int ans = INF;
 84     for(int i = 0; i < 4; ++i) scanf("%s",g[i]);
 85     // first
 86     Init();
 87     for(int i = 0; i < 4; ++i)
 88     for(int j = 0; j < 4; ++j) if(g[i][j] == 'b'){
 89         A[i*4 + j][16] = 1;
 90     }
 91     int t = Gauss();
 92     if(t != -1) ans = min(ans,t);
 93     //second
 94     Init();
 95     for(int i = 0; i < 4; ++i)
 96     for(int j = 0; j < 4; ++j) if(g[i][j] == 'w'){
 97         A[i*4 + j][16] = 1;
 98     }
 99     t = Gauss();
100     if(t != -1) ans = min(ans,t);
101     if(ans != INF)
102         printf("%d\n",ans);
103     else
104         printf("Impossible\n");
105     return 0;
106 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/3978382.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值