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

题目大意:

  有一个m*n的棋盘(1 ≤ M ≤ 15; 1 ≤ N ≤ 15),每个格子有两面分别是0或1,每次可以对一个格子做一次翻转操作,将被操作的格子和与其相邻的周围4个格子都会进行翻转。问做少做多少次翻转可以将所有格子翻转成0,输出翻转方案(每个棋子的翻转次数)。没有方案时输出“IMPOSSIBLE”。

Sample Input

4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1

Sample Output

0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0

解题思路:

  首先需要明确每个格子只有两种情况,就是要么翻和要么不翻,因为翻奇数次都与翻1次,而翻偶数次等于没翻。再来看一下数据范围n和m最大都为15,范围不是很大,但是全部枚举的话应该也会超时,所以我们要找到一个方案减少枚举量,我们发现如果一行的状态已经确定了,那么它接下来的是不是都确定了。下一行都要保证上一行全为0就可以了,最后只需要判断一下最后一行是否都为0就可以了,而第一行有n个棋子,它的状态也就是有2^n种。我们可以用一个含有16位的二进制数来表示它的状态,如果第i位为1表示该格子需要翻转,如果为0,则表示不翻转,翻转完第一行,仅接着翻第2行,每行的状态由其上一行的状态所确定。这样只要判断最后一行是否可以全部为0即可,如果为0,判断是否比答案更小,如果更小,则对答案进行更新。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<cmath>
#include<list>
#include<deque>
#include<cstdlib>
#include<bitset>
#include<stack>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int n,m,mp[][],tmp[][],cnt[][],ans[][],res;
void flip(int x,int y) //翻转,用异或符操作
{
tmp[x][y]^=;
tmp[x+][y]^=;
tmp[x-][y]^=;
tmp[x][y+]^=;
tmp[x][y-]^=;
}
int main()
{
ios_base::sync_with_stdio(false); cin.tie();
cin>>m>>n;
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
cin>>mp[i][j];
}
}
res=INF; //初始答案为无穷大
for(int s=;s<(<<n);s++) //枚举第一行的所有状态
{
int tot=;
memset(cnt,,sizeof(cnt));
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
tmp[i][j]=mp[i][j];
}
}
for(int i=;i<n;i++)
{
if(((s>>i)&)) //如果第i+1位为1,则对其进行翻转
{
tot++;
cnt[][i+]=;
flip(,i+);
}
}
for(int i=;i<=m;i++) //翻转第2至m行
{
for(int j=;j<=n;j++)
{
if(tmp[i-][j])
{
tot++;
cnt[i][j]=;
flip(i,j);
}
}
}
int flag=;
for(int i=;i<=n;i++) //判断是否合法
{
if(tmp[m][i]!=)
{
flag=;
break;
}
}
if(flag&&tot<res) //合法且比当前答案小对答案进行更新
{
res=tot;
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
ans[i][j]=cnt[i][j];
}
}
}
}
if(res==INF) //不能实现
{
cout<<"IMPOSSIBLE"<<endl;
return ;
}
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
if(j==) cout<<ans[i][j];
else cout<<" "<<ans[i][j];
}
cout<<endl;
}
return ;
}

题目链接:http://poj.org/problem?id=1753

题目大意:

  给你一个4*4的棋盘,上面摆了16个棋子,每个棋子有两面,一面是黑色一面是白色,给出棋盘的初始状态,每次可以翻一个棋子,而且每次翻的时候连着四周的棋子一起翻,问最少几次操作可以使棋盘全变为白棋或者黑棋。

思路:

  首先可以用DFS做,数据范围较小,最多翻16个棋子(每个棋子要么翻要么不翻,再翻就和原来一样了),枚举翻的棋子数,然后用DFS搜索翻该棋子数的所有情况,然后进行判断是否全为黑或全为白,就可以找出答案。

  当然也可以用二进制枚举的方法,总共16个棋子,对应2^16种状态,直接暴力枚举全部枚举全部情况,保留答案的最小值,与上面那题类似。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<cmath>
#include<list>
#include<deque>
#include<cstdlib>
#include<bitset>
#include<stack>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int mp[][],tmp[][],ans;
void flip(int x,int y) //翻转
{
tmp[x][y]^=;
tmp[x+][y]^=;
tmp[x-][y]^=;
tmp[x][y+]^=;
tmp[x][y-]^=;
}
int main()
{
ios_base::sync_with_stdio(false); cin.tie();
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
char c;
cin>>c;
if(c=='w') mp[i][j]=;
else mp[i][j]=;
}
}
ans=;
for(int s=;s<(<<);s++) //枚举所有情况
{
int tot=;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
tmp[i][j]=mp[i][j];
}
for(int i=;i<;i++)
{
if((s>>i)&)
{
int x=(i+)/+; //判断第i+1棋子的坐标,然后对其翻转
int y=(i+)%;
if(y==){x--;y=;}
tot++;
flip(x,y);
}
}
int flag=;
for(int i=;i<=;i++) //判断是否合法
{
for(int j=;j<=;j++)
{
if(tmp[i][j]!=tmp[][])
{
flag=;
break;
}
}
if(flag==) break;
}
if(flag&&tot<ans) //合法更新答案
ans=tot;
}
if(ans==)
cout<<"Impossible"<<endl;
else
cout<<ans<<endl;
return ;
}

poj-3279 poj-1753(二进制枚举)的更多相关文章

  1. (简单) POJ 3279 Fliptile,集合枚举。

    Description Farmer John knows that an intellectually satisfied cow is a happy cow who will give more ...

  2. POJ 3279 Fliptile (二进制+搜索)

    [题目链接]click here~~ [题目大意]: 农夫约翰知道聪明的牛产奶多. 于是为了提高牛的智商他准备了例如以下游戏. 有一个M×N 的格子,每一个格子能够翻转正反面,它们一面是黑色,还有一面 ...

  3. POJ.3279 Fliptile (搜索+二进制枚举+开关问题)

    POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...

  4. POJ 3279 Fliptile (二进制枚举)

    <题目链接> <转载于 >>> > 题目大意: 给定一个M*N矩阵,有些是黑色(1表示)否则白色(0表示),每翻转一个(i,j),会使得它和它周围4个格变为另 ...

  5. POJ 3279 Fliptile(反转 +二进制枚举)

    Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13631   Accepted: 5027 Descrip ...

  6. poj 3279 Fliptile(二进制)

    http://poj.org/problem?id=3279 在n*N的矩阵上,0代表白色,1代表黑色,每次选取一个点可以其颜色换过来,即白色变成黑色,黑色变成白色,而且其上下左右的点颜色也要交换,求 ...

  7. 【枚举】POJ 3279

    直达–>POJ 3279 Fliptile 题意:poj的奶牛又开始作孽了,这回他一跺脚就会让上下左右的砖块翻转(1->0 || 0->1),问你最少踩哪些砖块才能让初始的砖块全部变 ...

  8. Poj(2784),二进制枚举最小生成树

    题目链接:http://poj.org/problem?id=2784 Buy or Build Time Limit: 2000MS   Memory Limit: 65536K Total Sub ...

  9. poj 3740 Easy Finding 二进制压缩枚举dfs 与 DLX模板详细解析

    题目链接:http://poj.org/problem?id=3740 题意: 是否从0,1矩阵中选出若干行,使得新的矩阵每一列有且仅有一个1? 原矩阵N*M $ 1<= N <= 16 ...

  10. poj 3977 Subset(折半枚举+二进制枚举+二分)

    Subset Time Limit: 30000MS   Memory Limit: 65536K Total Submissions: 5721   Accepted: 1083 Descripti ...

随机推荐

  1. Hbase存储模式

    以key.value的结构存储数据;  (table,rowkey,family,colum,timestamp)构成数据的key,value存储数据

  2. MyCat数据库中间件 - 分库

    MyCat MyCat用于解耦分布式数据库与java,比如分库分表以后,需要查询某条数据时,需要java根据需要查的数据先计算去哪个库查,然而有了Mycat就不用自己计算怎么存储,怎么查询了.MyCa ...

  3. elasticsearch概念及倒排索引简单介绍

    一.概念 集群:一个或者多个节点组织在一起 节点:一个节点是集群中的一个服务器,由一个名字来标识,默认是一个随机的漫威角色名字. 分片:将索引划分为多份的能力,允许水平分割和扩展容量,多个分片相应请求 ...

  4. MySQL磁盘写入策略以及数据安全性的相关参数

     转载自:http://blog.itpub.net/22664653/viewspace-1063134/   innodb_flush_log_at_trx_commit和sync_binlog ...

  5. vue之v-for使用说明

    demo.html <!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/19 ...

  6. 一、MyCat的搭建

    一.什么是mycat 简单直接点就是,MyCat其实就是一个数据库的中间件!一般我们都是app直接到数据库!有了MyCat以后,就是app到MyCat然后再访问数据库. mycat是个中间件,它负责连 ...

  7. mvc学习过程碰到问题

    Fluent API配置 单例模式+Autofac 批量注入

  8. codeforces231C

    To Add or Not to Add CodeForces - 231C A piece of paper contains an array of n integers a1, a2, ..., ...

  9. codeforces559B

    Equivalent Strings CodeForces - 559B Today on a lecture about strings Gerald learned a new definitio ...

  10. luogu T40984Chino的成绩

    Chino的成绩 题目描述 Chino非常注重自己的成绩 Chino有m种方式给自己增加rp以增加成绩,她的每种增加rp的方式都有n个阶段,第i种的第j个阶段增加的rp表示为Aij​,表示连续进行了j ...