NC235250 牛可乐的翻转游戏

题目

题目描述

牛可乐发明了一种新型的翻转游戏!

在一个有 \(n\) 行 \(m\) 列的棋盘上,每个格子摆放有一枚棋子,每一枚棋子的颜色要么是黑色,要么是白色。每次操作牛可乐可以选择一枚棋子,将它的颜色翻转(黑变白,白变黑),同时将这枚棋子上下左右相邻的四枚棋子的颜色翻转(如果对应位置有棋子的话)。

牛可乐想请你帮他判断一下,能否通过多次操作将所有棋子都变成黑色或者白色?如果可以,最小操作次数又是多少呢?

输入描述

第一行两个整数 \(n,m(1\leq n\leq 100,1\leq m\leq 10)\),代表棋盘的行数和列数。

之后 \(n\) 行,每行 \(m\) 个数字,第 \(i\) 个数字如果为 \(0\) ,代表对应位置的棋子为白色,如果为 \(1\) 则为黑色。

输出描述

如果无法将所有棋子变成一个颜色,输出 "Impossible"(不含引号),否则输出变成一个颜色的最小操作次数。

示例1

输入

4 4
1001
1101
1001
1000

输出

4

题解

思路

知识点:状压枚举+递推。

首先注意到可以通过对第 \(i\) 行操作第 \(i-1\) 行全部按灭或按亮,于是可以通过这个操作将状态变换成最后一行的亮灭,而前三行统一亮灭。而基于这些操作的最后一行如果不是全灭或全亮就说明初状态不可行,否则可行。

然后,对于第一行会有 \(2^m\) 种初状态,只要遍历这些状态,分别执行上述操作即可。

具体操作上,可以用一个 \(m\) 位二进制 \(change[i]\) 表示对 \(i\) 行灯的开关操作,\(1\) 表示按,\(0\) 表示不按。对于 \(i\) 行的状态 \(a[i]\) 而言,需要将 \(1\) 的位置取反且周围 \(4\) 个也取反,\(0\) 的位置不变,即\(a[i] \oplus change[i] \oplus (change[i]>>1) \oplus (change[i]<<1)\) ;对于 \(i-1\) 行的状态 \(a[i-1]\) 而言,即 \(a[i-1] \oplus change[i]\) ,观察这个性质,我们可以将下一次按钮方式设置为本行的灯状态,做到用下一行按本行的灯;对于 \(i+1\) 行的状态 \(a[i+1]\) 而言,即 \(a[i+1] \oplus change[i]\)。需要注意 \(change[i] << 1\) 可能在int里面使范围外的二进制码改变需要加上限制 \((change[i] << 1) \& ((1<<m)-1))\) 。

最后计算 \(change[0\cdots m-1]\) 可以消去二进制最后一位 \(1\) 来计数。

时间复杂度 \(O(nm)\)

空间复杂度 \(O(nm)\)

本题为POJ1753的变种。

代码

#include <bits/stdc++.h>

using namespace std;

int n,m;
int a[107],b[107],cur[107],change[107]; int cal(int num){
int ans = 0;
while(num){
ans++;
num &= num-1;
}
return ans;
} int sol(int a[]){
int ans = ~(1<<31);
for(change[0] = 0;change[0]<(1<<m);change[0]++){
int sum = 0;
cur[0] = a[0];
for(int i = 0;i<n;i++){
sum += cal(change[i]);
cur[i] = cur[i] ^ change[i] ^ (change[i]>>1) ^ ((change[i]<<1)&((1<<m)-1));
cur[i+1] = a[i+1] ^ change[i];
change[i+1] = cur[i];
}
if(!cur[n-1]) ans = min(ans,sum);
}
return ans;
} int main(){
std::ios::sync_with_stdio(0);
cin>>n>>m;
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
char tmp;
cin>>tmp;
if(tmp == '1') a[i] |= (1<<j);
else if(tmp == '0') b[i] |= (1<<j);
}
}
int ans = min(sol(a),sol(b));
if(ans>n*m) cout<<"Impossible"<<'\n';
else cout<<ans<<'\n';
return 0;
}

NC235250 牛可乐的翻转游戏的更多相关文章

  1. [Swift]LeetCode293. 翻转游戏 $ Flip Game

    You are playing the following Flip Game with your friend: Given a string that contains only these tw ...

  2. Luogu 1764 翻转游戏 - 枚举 + 搜索

    题目描述 kkke在一个n*n的棋盘上进行一个翻转游戏.棋盘的每个格子上都放有一个棋子,每个棋子有2个面,一面是黑色的,另一面是白色的.初始的时候,棋盘上的棋子有的黑色向上,有的白色向上.现在kkke ...

  3. 牛客网 牛可乐发红包脱单ACM赛 C题 区区区间间间

    [题解] 我想到了两种解法. 一种是扫描线+线段树+单调栈. 另一种方法是O(n)的,比较巧妙. 考虑每个数在哪些区间可以作为最小数.最长的区间就是它向左右走,直到有数字比它小,这个可以用单调栈维护. ...

  4. 【2018寒假集训 Day1】【位运算】翻转游戏

    翻转游戏(flip) [问题描述] 翻转游戏是在一个 4 格×4 格的长方形上进行的,在长方形的 16 个格上每 个格子都放着一个双面的物件.每个物件的两个面,一面是白色,另一面是黑色, 每个物件要么 ...

  5. [LeetCode] 293. Flip Game 翻转游戏

    You are playing the following Flip Game with your friend: Given a string that contains only these tw ...

  6. [LeetCode] 294. Flip Game II 翻转游戏 II

    You are playing the following Flip Game with your friend: Given a string that contains only these tw ...

  7. 294. 翻转游戏 II

    题目: 链接:https://leetcode-cn.com/problems/flip-game-ii/ 你和朋友玩一个叫做「翻转游戏」的游戏,游戏规则:给定一个只有 + 和 - 的字符串.你和朋友 ...

  8. [LeetCode] Flip Game 翻转游戏

    You are playing the following Flip Game with your friend: Given a string that contains only these tw ...

  9. 牛客1024B 石头游戏

    题目描述 石头游戏在一个 \(n\) 行 \(m\) 列 \((1\leq n,m \leq 8)(1≤n,m≤8)\) 的网格上进行,每个格子对应一种操作序列,操作序列至多有10种,分别用0~9这1 ...

随机推荐

  1. 2021.07.23 P3275 糖果(差分约束)

    2021.07.23 P3275 糖果(差分约束) [P3275 SCOI2011]糖果 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 重点: 1.为了满足更多更多约束条件,合适地 ...

  2. Blazor Bootstrap 组件库 Toast 轻量弹窗组件介绍

    轻量级 Toast 弹窗 DEMO https://www.blazor.zone/toasts 基础用法: 用户操作时,右下角给予适当的提示信息 <ToastBox class="d ...

  3. WPFApplication类

    Application类 应用程序类Application,以下代码自动生成且在程序中不可见,定义程序入口点方法以及程序启动程序,整个程序生命周期为执行完Main()方法里的程序.对于自定义的应用程序 ...

  4. [题解] 序列(sequence)

    题目大意 给定一个长度为 \(N\)​ 的非负整数序列 \(A_1,A_2, \ldots ,A_N\)​,和一个正整数 \(M\)​.序列 \(A\) ​满足 \(\forall 1 \le i \ ...

  5. 团队Beta5

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 **过去两天完成了哪些任务 ** 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 无 接下来的计划 无 **还剩下哪些任务 ...

  6. MySQL实时在线备份恢复方案

    开源Linux 长按二维码加关注~ 上一篇:2020年MySQL数据库面试题总结 快照和复制技术的结合可以保证我们得到一个实时的在线MySQL备份解决方案. 当主库发生误操作时,只需要恢复备库上的快照 ...

  7. 思索 p5.js 的最佳实践

    思索 p5.js 的最佳实践 本文写于 2020 年 12 月 18 日 p5.js 是一个 JavaScript 库,用于为艺术家.设计师提供更容易上手的创意编程. 它有着完整的一套基于 Canva ...

  8. 我怀疑这是IDEA的BUG,但是我翻遍全网没找到证据!

    你好呀,我是歪歪. 前几天有朋友给我发来这样的一个截图: 他说他不理解,为什么这样不报错. 我说我也不理解,把一个 boolean 类型赋值给 int 类型,怎么会不报错呢,并接着追问他:这个代码截图 ...

  9. 从MySQL全备文件中恢复单个库或者单个表

    从MySQL全备文件中恢复单个库或者单个表 提取建库语句 sed -n '/^-- Current Database: db_cms/,/^-- Current Database: `/p' back ...

  10. Java中如何快捷的创建不可变集合

    在Java 9中又新增了一些API来帮助便捷的创建不可变集合,以减少代码复杂度. 本期配套视频:Java 9 新特性:快速定义不可变集合 常规写法 以往我们创建一些不可变集合的时候,通常是这样写的: ...