poj 3279 Fliptile(搜索,枚举)

版权声明:本文为博主原创文章,转载请附带博主链接。 https://blog.csdn.net/pashuihou/article/details/82667649

【题目链接】
http://poj.org/problem?id=3279

题目意思

给一个n*m的矩阵,1代表黑色方块,0代表白色方块。现在一只牛要把全部方块翻成白色,它一脚下去能把白变黑,黑变白。由于蹄子太大当它踩某格时候周围上下左右都将根随变换。问牛最少踩的次数的方案,如果有多种输出字典序小的。无法则输出 “IMPOSSIBLE”

解题思路

因为白的踩一变黑的,黑的踩一次变白的,所以每个格子最多踩一次就可以了,多踩又变回去了。当第n行确定,为了保证第n行的1都变成0,第n+1行踩的位子只能是上行为1的位子。所以当第1行确定了整个图踩的方案就确定了。只要判断最后一行踩完后是否全为0,是则方案可行否则不可以行。枚举第一行全部的踩法找最优。
可以开二维数组记图,也可以用二进制来表示。(n不大)具体看代码吧

代码部分


#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define LL long long
#define inf 0x3f3f3f3
const int N = 1e5+5;
int mp[16]; 
int a[16];   //记录踩完后的图 
int b[16];   //记录最小方案 
int c[16];  //记录每层踩的位子 
int mn;
int n,m;
void dfs(int i,int k,int ans)  //行数;第i-1行的值,同样数第i行需要踩的格子;步数 
{
    c[i] = k;
    if (i == n){
        if (!k && mn > ans){
            mn = ans;
            for (int i = 0; i < n; i++)
                b[i] = c[i];
        }
        return;
    }
    a[i] ^= mp[i];   //拿两个变量来记录本行和下一行也可以 
    int s = 0;
    for (int j = 1; j <= k;j <<= 1){
        if (j&k){
            s++;
            a[i] ^= j;           //本身 
            if (j < (1<<(m-1)))  //右 
                a[i] ^= (j<<1);  
            if (j != 1) //左 
                a[i] ^= (j>>1);
            a[i+1] ^= j;    下 
        }
    }
    dfs(i+1,a[i],ans+s);
}
int main()
{
    while (~scanf("%d %d",&n,&m))
    {
        mn = inf;
        memset(mp,0,sizeof(mp));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++){
                int t;
                scanf("%d",&t);
                mp[i] |= t<<j;
            }
        for (int i = 0; i < (1<<m); i++){
            memset(a,0,sizeof(a)); 
            dfs(0,i,0);
        }
        if (mn == inf)
            printf("IMPOSSIBLE\n");
        else
            for (int i =0; i < n; i++){
                int k = b[i];
                for (int i = 0; i < m; i++){
                    if (k&1)
                        printf("1");
                    else printf("0");
                    k >>= 1;
                    printf("%c",i != m-1? ' ':'\n');
                }
            }
    }
    return 0;
} 
/*
4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
1 4
0 1 1 1
2 4
0 0 1 1
0 0 1 1
*/

猜你喜欢

转载自blog.csdn.net/pashuihou/article/details/82667649
今日推荐