<题目链接>

<转载于 >>> >

题目大意:
 给定一个M*N矩阵,有些是黑色(1表示)否则白色(0表示),每翻转一个(i,j),会使得它和它周围4个格变为另一个颜色,要求翻转最少的点,使得变为全白色的矩阵,输出这个标记了翻转点的矩阵,如果有多个最优解,输出字典序最小的那个矩阵,若没有解,输出IMPOSSIBLE。

解题分析:

由于一个点翻转两次则返回原来的状态,所以最优解每个点最多翻转一次,但是2^(M*N)过大,所以2^N枚举第一行的所有翻转方式(逆字典序枚举),确定一种方式之后第二行也就随之确定了,因为如果第一行处理后没有翻回白色的点:(i,j),必须在第二行(i+1,j)翻回,否则将无法返回。反之第二行其他的点都处理为不翻转,要不然上一行的点会翻回黑色而无法改变。第二行ok后同理解决第三行,以此类推。处理到最后一行如果不是全白就输出IMPOSSIBLE。否则更新结果。

即,用二进制枚举第一行的翻转情况,然后2~n-1行按照上一行的情况来翻转,最后再判断最后一行是否全部为0,如果为0,则记录下翻转次数,随时更新答案。

  1.  
  1. #include<cstdio>
  2. #include<cstring>
  3. int t[][], tem[][], m[][];
  4. //这里用一个数组记录翻转次数,再配合原来的点数,就能判断反转后的点数,这里很巧妙
  5. int M,N,dir[][] = { ,,,,,,-,,,- };
  6.  
  7. int get(int x, int y)//获得x,y点的颜色 //它本身的点数,再加上周围四个点反转的次数,就能得到它的真实点数
  8. {
  9. int c = t[x][y];
  10. for (int i = ; i < ; i++)
  11. {
  12. int x1 = x + dir[i][], y1 = y + dir[i][];
  13. c += tem[x1][y1];
  14. }
  15. return c % ;
  16. }
  17.  
  18. int cal() //计算2行及之后的,有解返回翻点数,无解返回-1
  19. {
  20. for (int i = ; i <= M; i++)
  21. for (int j = ; j <= N; j++)
  22. if (get(i - , j) == )
  23. tem[i][j] = ;
  24. //得到前n-1行的翻转次数
  25.  
  26. for (int i = ; i <= N; i++)
  27. if (get(M, i))return -; //如果最后一行有一个点不为0,说明枚举的第一行不符合要求s
  28. int res = ;
  29. for (int i = ; i <= M; i++)
  30. for (int j = ; j <= N; j++)
  31. res += tem[i][j];
  32. return res; //记录下需要翻转的总次数
  33. }
  34.  
  35. int main()
  36. {
  37. int min = -; //次数>0可以这样初始化
  38. scanf("%d%d", &M, &N);
  39. for (int i = ; i <= M; i++)
  40. for (int j = ; j <= N; j++)
  41. scanf("%d", &t[i][j]);
  42. for (int i = ; i < ( << N); i++) //枚举第一行的所有情况
  43. {
  44. memset(tem, , sizeof(tem)); //初始化翻转数组
  45. for (int j = ; j <= N; j++)
  46. tem[][j] = (i >> (j - )) & ; //根据二进制得到第一行的翻转情况,这个技巧一定要掌握
  47.  
  48. int num = cal();
  49. if (num >= && (min< || min>num)) //取情况成立并且总翻转次数最小的
  50. {
  51. min = num;
  52. memcpy(m, tem, sizeof(tem)); //记录下最后的翻转矩阵
  53. }
  54. }
  55.  
  56. if (min == -)printf("IMPOSSIBLE\n");
  57. else
  58. {
  59. for (int i = ; i <= M; i++)
  60. for (int j = ; j <= N; j++)
  61. printf("%d%c", m[i][j], j == N ? '\n' : ' ');
  62. }
  63. return ;
  64. }

2018-08-30

POJ 3279 Fliptile (二进制枚举)的更多相关文章

  1. poj 3279 Fliptile(二进制)

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

  2. poj 3279 Fliptile(二进制搜索)

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

  3. POJ 3279 Fliptile[二进制状压DP]

    题目链接[http://poj.org/problem?id=3279] 题意:给出一个大小为M*N(1 ≤ M ≤ 15; 1 ≤ N ≤ 15) 的图,图中每个格子代表一个灯泡,mp[i][j] ...

  4. POJ - 3279 Fliptile (枚举)

    http://poj.org/problem?id=3279 题意 一个m*n的01矩阵,每次翻转(x,y),那么它上下左右以及本身就会0变1,1变0,问把矩阵变成全0的,最小需要点击多少步,并输出最 ...

  5. POJ 3279 Fliptile【枚举】

    题意: 又是农夫和牛的故事...有m*n个黑白块,黑块的背面是白块,白块背面是黑块,一头牛踩一块,则这个块的上下左右的方块都会转动,问至少踩多少块,才会使所有块都变成白色? 分析: 还是开关问题,同样 ...

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

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

  7. 状态压缩+枚举 POJ 3279 Fliptile

    题目传送门 /* 题意:问最少翻转几次使得棋子都变白,输出翻转的位置 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转 */ #include < ...

  8. POJ 3279 Fliptile(翻格子)

    POJ 3279 Fliptile(翻格子) Time Limit: 2000MS    Memory Limit: 65536K Description - 题目描述 Farmer John kno ...

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

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

随机推荐

  1. Linux之更改Nginx映射默认根目录

     更改nginx映射默认根目录: 1.打开默认配置文件:sudo  vi /etc/nginx/sites-available/default 2.修改配置:root /var/www/html/xx ...

  2. SAP笔记---非-现存任务/请求XXX上的请求锁定

    不管在SAP中的哪个系统在点击修改程序时都有可能出现以下图中的报错: 已找到解决办法,步骤如下: 1,se11中查看tlock表找到以上提到的请求号记录: 2,进入se16n,输入请求号,在事务代码输 ...

  3. luogu P2900 [USACO08MAR]土地征用Land Acquisition

    写这道题时,预处理部分少打了等号,吓得我以为斜率优化错了或者被卡精了 mmp 首先有一个很明显的结论(逃),就是一个土地如果长(\(x\))与宽(\(y\))都比另一个土地小,那么这个土地一定可以跟那 ...

  4. 洛谷4718【模板】Pollard-Rho算法

    传送门 Description: 给定T个数,分别求出它们的最大质因数 Solution: 其实大概框架是很容易想到的 对于一个数n 找到它的一个因数x 判断这个因数是不是质数 如果是质数就更新答案 ...

  5. Kali2.0第一节

    kali2.0很好的做了工具缩减,以及图形处理,重要的是msf更快了!汉化也远远超过了1.0 如果想要汉化,选择设置里面的Region&language  将language选择设置为中文,注 ...

  6. Android BroadcastReceiver解析

    目录   示意图 1. 定义 即 广播,是一个全局的监听器,属于Android四大组件之一 Android 广播分为两个角色:广播发送者.广播接收者 2. 作用 监听 / 接收 应用 App 发出的广 ...

  7. windows下caffe GPU版本配置

    由于项目需要,所以在自己本子上配置了一下windows下GPU版本的caffe; 硬件:  win10    ;      gtx1070独显(计算能力6.1): 安装软件:     cudnn-8. ...

  8. Filter功能

    在HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest .根据需要检查HttpServletRequest,也可以修改HttpServletR ...

  9. javascrip学习之 数据类型和变量

    JavaScript 是脚本语言.是一种轻量级的编程语言.是可插入 HTML 页面的编程代码,可由所有的现代浏览器执行. JavaScript的语法和Java语言类似,每个语句以;结束,语句块用{.. ...

  10. React-Native 之 项目实战(一)

    前言 本文有配套视频,可以酌情观看. 文中内容因各人理解不同,可能会有所偏差,欢迎朋友们联系我. 文中所有内容仅供学习交流之用,不可用于商业用途,如因此引起的相关法律法规责任,与我无关. 如文中内容对 ...