POJ 3279 Fliptile 状态压缩,思路 难度:2

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

明显,每一位上只需要是0或者1,

遍历第一行的所有取值可能,(1<<15,时间足够)对每种取值可能:

对于第0-n-2行,因为上一行和本身行都已确定,所以可以确定下一行

最后检查第n-1行是否满足条件即可

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int maz[15][15];
int op[15][15];
int ans[15][15],mn;
int n,m;
void getop(int sta){
        memset(op,0,sizeof(op));
        for(int i=0;i<n;i++){
                if(sta&(1<<i)){
                        op[0][i]=1;
                }
        }
}
int getone(){
        int num=0;
        for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                        num+=op[i][j];
                }
        }
        return num;
}
const int dx[4]={0,-1,0,0};
const int dy[4]={0,0,1,-1};
bool in(int x,int y){
        return x>=0&&x<n&&y>=0&&y<m;
}
bool judge(int x,int y){
        int num=maz[x][y];
        for(int i=0;i<4;i++){
                int tx=x+dx[i],ty=y+dy[i];
                if(in(tx,ty))num+=op[tx][ty];
        }
        return (num&1)==0;
}
int main(){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                        scanf("%d",maz[i]+j);
        int mn=0x7ffffff;
        for(int sta=0;sta<(1<<n);sta++){
                getop(sta);
                for(int i=0;i<n-1;i++){
                        for(int j=0;j<m;j++){
                                if(!judge(i,j)){
                                        op[i+1][j]=1;
                                }
                        }
                }
                bool fl=true;
                for(int j=0;j<m;j++){
                        if(!judge(n-1,j)){
                                fl=false;
                                break;
                        }
                }
                if(fl){
                        int num=getone();
                        if(num<mn){
                                for(int i=0;i<n;i++){
                                        copy(op[i],op[i]+m,ans[i]);
                                }
                                mn=num;
                        }
                }
        }
        if(mn<=n*m)
        for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                        printf("%d%c",ans[i][j],j==m-1?‘\n‘:‘ ‘);
                }
        }
        else puts("IMPOSSIBLE");

        return 0;
}

  

时间: 2024-11-08 17:22:33

POJ 3279 Fliptile 状态压缩,思路 难度:2的相关文章

Fliptile POJ - 3279(状态压缩)

题意:给你一个n * m的矩阵,元素为0/1, 求把所有的元素变成0所需要的最少操作.(每对一个格子操作,该十字格的元素反转) 分析:一看数据量 <= 15, 就有点状态压缩的感jio.从小到大枚举第一行的操作,因为第一行的操作决定了后面所有的操作,所以最后判断对于第一行的操作是不是符合题意即可. 代码: 1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <

状态压缩+枚举 POJ 3279 Fliptile

题目传送门 1 /* 2 题意:问最少翻转几次使得棋子都变白,输出翻转的位置 3 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转 4 */ 5 #include <cstdio> 6 #include <cstring> 7 #include <algorithm> 8 using namespace std; 9 10 const int MAXN = 20; 11 const int INF = 0x3f3f3f3

Mondriaan&#39;s Dream - POJ 2411(状态压缩)

题目大意:有一些1*2的矩形,现在用这些小矩形覆盖M*N的大矩形,不能重复覆盖,并且要覆盖完全,求有多少种覆盖方式. 分析:可以使用1和0两种状态来表示这个位置有没有放置,1表示放置,0表示没有放置,可以有三种放置方式. 一,竖着放. 二,不放.三,横着放.直接DFS这些情况就行了................还是递归容易理解. 代码如下: =============================================================================

【POJ 3279 Fliptile】开关问题,模拟

题目链接:http://poj.org/problem?id=3279 题意:给定一个n*m的坐标方格,每个位置为黑色或白色.现有如下翻转规则:每翻转一个位置的颜色,与其四连通的位置都会被翻转,但注意只扩散一圈,不是连锁反应. 求最少翻转几个位置能够使所有n*m个位置都变为白色.若有解,求字典序最小的翻转方案(给出每个位置的翻转次数). 数据范围:n, m 属于 [1, 15] 思路:我们把翻转方案中的翻转称为“主动翻转”,翻转过程中受邻居影响而发生的翻转称为“被动翻转”.观察例子可得出如下几个

POJ 3279(Fliptile)题解

以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑色所需翻转的是哪些棋子(这句话好长...). [题目分析] 盯着奇怪的题目看了半天发现和奶牛没什么卵关系..奶牛智商高了产奶高是什么鬼说法... 这题刚开始被放到搜索的分类下了..然而这和搜索有什么关系..没经验所以想了各种和搜索沾边的方法,结果没想出解法,直到看了网上的题解,压根不是搜索啊有木有.

POJ 3311 【状态压缩DP】

题意: 给n个点,给出矩阵代表i到j单向边的距离. 要求,不介意访问每个点的次数,要求访问完每个点,使得路程总和最小. 思路: 由于不介意访问每个点的次数,所以可以先进行FLOYD求出任意两个点之间的最短路,然后就是DP. 同样的,1代表有访问过,0代表没访问过. dp[s][j]代表访问状态为s的情况下最终到达点j的最优值. 枚举状态s中每一个可以到达的点,从所有可能的点中枚举对其进行更新. 关于状态压缩的细节方面,注意从左边数第i位是从0开始数的,所以第i位代表第i+1个点. 然后状态的总数

POJ 3254 【状态压缩DP】

题意: 给一块n*m的田地,1代表肥沃,0代表贫瘠. 现在要求在肥沃的土地上种草,要求任何两个草都不能相邻. 问一共有多少种种草的方法. 种0棵草也是其中的一种方法. n和m都不大于12. 思路: 状态压缩DP,dp[i][j]代表在第i行状态j一共有多少种可能的种植方法. j是二进制转化而来的状态,0代表不种草,1代表种草. dp[i]只受到两个限制,即dp[i-1]的某种状态,和当前土地的贫瘠状况. 只要保证&操作之后重复的为0就可以了 最后输出sum(dp[n][1...w])(w代表一共

poj 3279 Fliptile (简单搜索)

Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16558   Accepted: 6056 Description Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in whic

POJ 3279 Fliptile(DFS+反转)

题目链接:http://poj.org/problem?id=3279 题目大意:有一个n*m的格子,每个格子都有黑白两面(0表示白色,1表示黑色).我们需要把所有的格子都反转成黑色,每反转一个格子,它上下左右的格子都会跟着反转.请求出用最小步数完成反转时每个格子反转的次数.有多个解时,输出字典序最小的一组. 解题思路:只要枚举第一行的2^m种情况,如果一个位置上一行是1,那这个位置一定要反转,因为只有这一行能改变上一行,所以每一行的状态都是由前一行决定的.只要最后判断最后一行是不是都是0即可,