zoukankan      html  css  js  c++  java
  • Fliptile POJ

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

    • 除最后一行,其余各行的1都可以通过下一行的翻转成为0
    • 也就是说除了最后一行,我们总可以通过翻转,将前n-1行变为0
    • 翻转偶数次 = 未翻转,翻转奇数次 = 翻转1次 故需要翻转则必为一次
    • 因此我们可以得出:若该位置上一个位置为1则翻转,反之则不翻转
    • 所以我们可以对第一行的翻转情况进行枚举,这里采用了二进制压缩的方法
    • 将第一行看作一个n位的二进制数字 找出1的所有位置即可
    • 在找1位置时 比如n = 4的情况 我们可以让每一种情况与 1000 0100 0010 0001进行&运算
     1 #include <map>
     2 #include <set>
     3 #include <cmath>
     4 #include <queue>
     5 #include <string>
     6 #include <vector>
     7 #include <cstdio>
     8 #include <cstring>
     9 #include <iostream>
    10 #include <algorithm>
    11 #define forn(i, n) for (int i = 0; i < (n); i++)
    12 #define forab(i, a, b) for (int i = (a); i <= (b); i++)
    13 #define forba(i, b, a) for (int i = (b); i >= (a); i--)
    14 #define mset(a, n) memset(a, n, sizeof(a))
    15 #define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
    16 #define P pair<int,int>
    17 #define fi first
    18 #define se second
    19 using namespace std;
    20 #define N 100005
    21 #define maxn 1005
    22 #define inf 0x3f3f3f3f
    23 #define ll long long
    24 int f[30][30];  //最终结果
    25 int g[30][30];  //原矩阵
    26 int t[30][30];  //临时答案
    27 int cnt, n, m;
    28 int xx[4] = {1, -1, 0, 0};
    29 int yy[4] = {0, 0, 1, -1};
    30 void flip(int i,int j)  //翻转
    31 {
    32     cnt++;
    33     f[i][j] = 1;  //需要翻转则肯定只翻转一次
    34     t[i][j] = !t[i][j];  //先将自己翻转
    35     forab(k,0,3)
    36     {
    37         if(i+xx[k]>-1&&j+yy[k]>-1)
    38         {
    39             t[i + xx[k]][j + yy[k]] ^= 1;
    40         }
    41     }
    42 }
    43 bool judge(int k)
    44 {
    45     cnt = 0;   //步数清零
    46     memcpy(t, g, sizeof(t));  //将初始情况复制到临时情况中
    47     forab(j,0,m-1)    //枚举第一行
    48     {
    49         if (k & (1 << (m - 1 - j))) //如果第j位是1
    50             flip(0, j);
    51     }
    52     forab(i, 1, n - 1)  //从第二行开始,如果某位置上面的位置为1则翻转
    53         forab(j, 0, m - 1) 
    54             if (t[i - 1][j]) 
    55                 flip(i, j);
    56     forab(j, 0, m - 1) //最后检查最后一行是否全为0
    57         if (t[n - 1][j]) 
    58             return false;
    59     return true;
    60 }
    61 int main()
    62 {
    63     int ans;
    64     int flag = -1;
    65     scanf("%d%d", &n, &m);
    66     forn(i, n)
    67         forn(j, m)
    68             scanf("%d", &g[i][j]);
    69     ans = m * n + 1;
    70     for (int i = 0; i < (1 << m);i++)
    71     {
    72         if(judge(i)&&cnt<ans)  //如果方法可行并且步数更优
    73         {
    74             ans = cnt;
    75             flag = i;  //记录一下第一行的情况
    76         }
    77     }
    78     mset(f, 0);  //初始化答案
    79     if(flag>=0)
    80     {
    81         judge(flag);  //上面记录的最优情况
    82         forn(i, n)
    83             forn(j, m)
    84                 printf("%d%c", f[i][j], j < m - 1 ? ' ' : '
    ');
    85     }
    86     else puts("IMPOSSIBLE");  //如果flag=-1证明所有情况都不可行
    87 }
    View Code
  • 相关阅读:
    [java]Java中父类强制转换成子类的原则
    基于 JWT + Refresh Token 的用户认证实践
    [java]idea设置及debug使用
    [java]Class类和Object类的关系
    [java]文件操作
    [java]javabean
    [java]string类型
    [java]求数据的hmac sha1的并用base64编码
    java 多线程——一个定时调度的例子
    设计模式 4 —— 迭代器和组合模式(组合)
  • 原文地址:https://www.cnblogs.com/zssst/p/11133256.html
Copyright © 2011-2022 走看看