poj--1753 Flip Game(二维反转)(高斯消元)

来源:互联网 发布:淘宝炫舞摘花怎么样 编辑:程序博客网 时间:2024/06/06 00:33

给定4乘4的01矩阵,反转成全0或者全1。求最小的反转次数。

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

解法一:进行两次二维反转,一次算出反转成全0的最少反转次数,一次算出反转成全1的最少反转次数。

详细方法:http://blog.csdn.net/fad_further/article/details/20571099

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int inf = 0x3f3f3f3f;const int dxy[5][2] = {{0, 0}, {1, 0}, {0, 1}, {-1, 0}, {0, -1} };int a[5][5], opt[5][5], ans, res;char str[10];bool judge(int x, int y){    int ret = a[x][y];    for(int i=0; i<5; i++){        int xx = x + dxy[i][0];        int yy = y + dxy[i][1];        if(xx >= 0 && xx < 4 && yy >= 0 && yy < 4)            ret += opt[xx][yy];    }    return ret % 2 == 0;}void cal(){    for(int i=1; i<4; i++)        for(int j=0; j<4; j++)            if(!judge(i - 1, j)){                opt[i][j] = 1;                ans++;            }}void cal2(){    for(int i=1; i<4; i++)        for(int j=0; j<4; j++)        if(judge(i - 1, j)){            opt[i][j] = 1;            ans++;        }}int main(){    for(int i=0; i<4; i++){        scanf("%s", str);        for(int j=0; j<4; j++)            a[i][j] = (str[j] == 'b') ? 1 : 0;    }    res = inf;    for(int i=0; i<(1 << 4); i++){  //to w        memset(opt, 0, sizeof(opt));        ans = 0;        for(int j=0; j<4; j++)        if(i & (1 << j)){            ans++;            opt[0][j] = 1;        }        cal();        bool flag = true;        for(int j=0; j<4; j++)if(!judge(3, j)){            flag = false;            break;        }        if(flag) res = min(res, ans);    }    for(int i=0; i<(1 << 4); i++){        memset(opt, 0, sizeof(opt));        ans = 0;        for(int j=0; j<4; j++)        if(i & (1 << j)){            ans++;            opt[0][j] = 1;        }        cal2();        bool flag = true;        for(int j=0; j<4; j++)if(judge(3, j)){            flag = false;            break;        }        if(flag) res = min(res, ans);    }    if(res < inf)printf("%d\n", res);    else puts("Impossible");    return 0;}

解法2:高斯消元

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int inf = 0x3f3f3f3f;const int dxy[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };const int maxn = 20;int a[maxn][maxn], x[maxn], xx[maxn];bool free_x[maxn];char str[5][5];int n = 4, var, equ;void Debug(){    puts("debug");    for(int i=0; i<equ; i++)    for(int j=0; j<=var; j++)    printf("%d%c", a[i][j], j == var ? '\n' : ' ');    puts("end");}void init(int q){    memset(a, 0, sizeof(a));    memset(free_x, true, sizeof(free_x));    var = equ = n * n;    for(int i=0; i<n; i++){        for(int j=0; j<n; j++){            int cur = i * n + j;            if(str[i][j] == 'w')                a[cur][var] = q;            else a[cur][var] = !q;            a[cur][cur] = 1;            for(int k=0; k<4; k++){                int xx = i + dxy[k][0];                int yy = j + dxy[k][1];                if(xx >= 0 && xx < n && yy >= 0 && yy < n){                    int tmp = xx * n + yy;                    a[cur][tmp] = 1;                }            }        }    }}int Gauss(int q){    init(q);//    Debug();    int col = 0, row = 0;    for(; col<var && row < equ; row++, col++){        int maxr = row;        for(int i=row+1; i<equ; i++)            if(a[i][col])            maxr = i;        if(a[maxr][col] == 0){            row--;            continue;        }        if(maxr != row)            for(int i=col; i<=var; i++)            swap(a[maxr][i], a[row][i]);        for(int i=row+1; i<equ; i++){            if(a[i][col] == 0) continue;            for(int j=col; j<=var; j++)                a[i][j] ^= a[row][j];        }    }    for(int i=row; i<equ; i++)        if(a[i][var]) return inf;    if(row < var){        int ans = inf;        for(int i=row-1; i>=0; i--){            int num = 0;            for(int j=row; j<var; j++)            if(free_x[j] && a[i][j]){                num++;            }            if(num > 1) continue;            free_x[i] = 0;        }        int num = var - row, d = 0;        for(int i=var-1; i>=0 && d < num; i--)            if(free_x[i])            xx[d++] = i;        for(int i=0; i<(1 << num); i++){            for(int j=0; j<num; j++)                if(i & (1 << j)) x[xx[j]] = 1;                else x[xx[j]] = 0;            for(int j=row-1; j>=0; j--){                int k;                for(k=j; k<var; k++)                    if(a[j][k]) break;                int id = k;                x[id] = a[j][var];                for(k=id+1; k<var; k++)                    if(a[j][k] && x[k])                    x[id] ^= 1;            }            int sum = 0;            for(int j=0; j<var; j++)                sum += x[j];            if(sum < ans) ans = sum;        }        return ans;    }    int ans = 0;    for(int i=var-1; i>=0; i--){        x[i] = a[i][var];        for(int j=i+1; j<var; j++)            if(a[i][j] && x[j])            x[i] ^= 1;        ans += x[i];    }    return ans;}int main(){    for(int i=0; i<n; i++)        scanf("%s", str[i]);    int ans1 = Gauss(0);    int ans2 = Gauss(1);    if(ans1 == inf && ans2 == inf)        puts("Impossible");    else printf("%d\n", min(ans1, ans2));    return 0;}


0 0