poj:1753_poj 1753-程序员宅基地

技术标签: 算法  枚举  poj  

poj 1753题学习笔记

1753 题是一个基本的枚举算法的题,基本解题思路就是暴力枚举,但是我们需要知道即便是暴力枚举,也是需要认真分析问题的。

题意:有一个4*4的棋盘,棋盘上有黑白格,每一次你可以翻其中的一个格子。一个格子(x,y)如果被翻,它相邻的前后左右四个格子(如果在棋盘上)也要翻转。现在给你一个初始的棋盘状态,问把这个棋盘翻转到全黑或全白的最少次数;若不能达到全黑或全白,输出Impossible。

思路:只有4*4的棋盘,同时格子只有黑白两面。对于同一个格子,翻两次和不翻没有区别。同时,我们会发现,假如第一行的状态已经确定,那么剩下的行的翻法其实也是确定了的。这样我们从原来需要枚举65536种,到现在只需要枚举第一行16种即可,所以,我们只需要按照求4个数的子集的方式,枚举第一行的翻法即可枚举所有可能形式。

所以,我们需要一个子集递归方法,一个步数求解方法,还有小方法例如判断当前是否全黑或全白、将当前棋子性质翻转等,即可实现枚举。

#include <stdio.h>
#include <iostream>
#include <string>
using namespace  std;
//成功
//暴力枚举,通过枚举第一行元素的组合方式进行暴力搜索
string s[4];//输入矩阵
string tmp[4];//当前棋子状态矩阵
bool b[4];//判断枚举,1-4的子集生成
int foot=100;//步子数
void back2(int x,int y){//将tmp中的元素性质翻转,例如b转成w,w转成b
    if(tmp[x][y]=='b')tmp[x][y]='w';
    else
        tmp[x][y]='b';
}
bool test(){//判断输入矩阵是否直接为全黑或者全白
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            if(s[i][j]!=s[0][0])return false;
        }
    }
    return true;
}
bool test2(){//判断当前棋子矩阵是否直接为全黑或者全白
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            if(tmp[i][j]!=tmp[0][0])return false;
        }
    }
    return true;
}
void genera(char flag){//将当前棋子矩阵变为全黑或者全白的步数
    int root=0;
    for(int i=0;i<4;i++){//将当前状态初始化为输入状态
        for(int j=0;j<4;j++){
            tmp[i][j]=s[i][j];
        }
    }
    for(int i=0;i<4;i++){//根据第一行的子集进行转换,即改变第一行的状态
        if(b[i]){
            root++;
            back2(0,i);
            back2(1,i);
            if(i<=2)back2(0,i+1);
            if(i>=1)back2(0,i-1);
        }
        
    }
        for(int i=0;i<4;i++){//根据第一行改变第二行
        if(tmp[0][i]!=flag){
            root++;
            tmp[0][i]=flag;
            back2(1,i);
            if(i<=2)back2(1,i+1);
            if(i>=1)back2(1,i-1);
            back2(2,i);
            
        }
    }
    for(int j=2;j<4;j++){//改变第三和第四行
    for(int i=0;i<4;i++){
        if(tmp[j-1][i]!=flag){
            root++;
            tmp[j-1][i]=flag;
            back2(j,i);
            if(i<=2)back2(j,i+1);
            if(i>=1)back2(j,i-1);
            if(j<=2)back2(j+1,i);
            
        }
    }
    }
    if(test2()&&root<foot){//如果当前棋子为全黑或全白则改变最小步数
        foot=root;
    }
    
}
void gen(int y){//第一行的全部子集
    if(y==4){
        genera('b');//全黑
        genera('w');//全白
    }
    else{
        b[y]=true;//使用位向量法构造第一行的全部子集数
        gen(y+1);
        b[y]=false;
        gen(y+1);
    }
}
int main(){
    for(int i=0;i<4;i++){
        cin>>s[i];
     b[i]=false;
    }
    if(test())
        cout<<0<<endl;//判断当前是否为已经排列好的矩阵
    else
    {//构造矩阵
        gen(0);
        if(foot!=100){
            cout<<foot<<endl;
        }
        else
            cout<<"Impossible"<<endl;//如果无法生成则输出
    }
    return 0;
}
在这里,我们需要知道,即使是枚举,也需要我们动脑筋认真分析问题。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wuzhenzi5193/article/details/80044425

智能推荐

数据结构|数组为什么这么快?-程序员宅基地

文章浏览阅读2.9k次,点赞8次,收藏10次。我相信在很多地方,大家在进行数据结构的比较的时候,说到数组,第一反应就是—快,但是为什么快呢?数组到底快在哪里呢?不知道大家是否有思考过这个问题,这篇文章,我就讲讲我对数组的一些看法,抛砖引玉,希望大家多多交流!文章目录数组到底哪里快?查找快吗?为什么数组能支持随机访问呢?答案:举例分析:我们要分析的第一个问题是:数组到底哪里快?查找快吗?可能有的同学第一反应利用数组进行查找的话,时间...

基于Matlab图像融合总结_图像融合代码matlab-程序员宅基地

文章浏览阅读273次。图像融合是一种将多幅图像信息合并成一幅新图像的技术,可以获得比单独图像更多的信息。在Matlab中,有多种方法可以实现图像融合,包括像素级融合、变换域融合和深度学习融合等。本文将总结这些方法,并提供相应的源代码。在实际应用中,根据图像融合的具体需求,选择合适的方法进行处理。这些方法可以互相结合,实现更细致、更精确的图像融合效果。希望本文提供的源代码和示例能够对您在Matlab中进行图像融合的工作有所帮助。基于Matlab图像融合总结。_图像融合代码matlab

算法题:平均数为k的最长连续子数组-程序员宅基地

文章浏览阅读1k次。平均数为k的最长连续子数组_平均数为k的最长连续子数组

HMC使用手册_台达hmc07-n511h52使用手册-程序员宅基地

文章浏览阅读1k次。今天偶然间想起了之前发生的一次运行事件,在这次故障中,物理服务器宕机,远程终端无法救急。于是就需要用到HMC(硬件管理控制台)进行底层的操作,之前对于这个工具的使用确实不多,所以今天就特意在网上找了一篇关于HMC使用的手册,这里给大家分享一下,如果大家想要看网页原版,下面是网址:HMC使用手册..._台达hmc07-n511h52使用手册

设置定时任务的几种方式_制定定时任务的方法-程序员宅基地

文章浏览阅读471次。◦ 前言 ◦ 解决方案 普通线程sleep的方式实现定时任务 Timer实现定时任务 ScheduledExecutorService实现定时任务 Handler实现定时任务 AlarmManager实现精确定时操作前言项目中总是会因为各种需求添加各种定时任务,所以就打..._制定定时任务的方法

mysql支持的平台和操作系统_MySQL支持的操作系统列表_MySQL-程序员宅基地

文章浏览阅读461次。我们使用GNU Autoconf,因此将MySQL移植到所有使用Posix线程和C++编译器的现代系统是可能的。(要求服务器支持线程。如果只是编译客户端代码,则只需要C++编译器)。我们主要在Linux(SuSE和Red Hat)、FreeBSD和Sun Solaris(版本8和9)上使用并开发本软件。已经报告MySQL可以在下列操作系统/线程包的组合上成功地进行编译。注意,对于很多操作系统,原生..._mysql可以运行在哪些平台

随便推点

Java 中应用Dijkstra算法求解最短路径_路由最短路径代码java-程序员宅基地

文章浏览阅读476次。Dijkstra算法是一个经典的解决最短路径问题的算法,在路由算法、导航系统等领域都有广泛的应用。它通过逐步选择距离起始节点最近的节点,并更新其邻接节点的最短距离,最终得到起始节点到其他所有节点的最短路径。然后,在一个循环中,每次选择距离最小且未加入最短路径集合的节点,将其加入最短路径集合,并更新其邻接节点的最短路径长度。它遍历所有未加入最短路径集合(shortestPathTreeSet)的节点,查找距离最小且未加入最短路径集合的节点,并返回其索引。数组来追踪起始节点到其他节点的最短路径长度,_路由最短路径代码java

Mybatis-plus解决selectOne查询多个会报错的问题_mybatisplus selectone-程序员宅基地

文章浏览阅读2w次,点赞13次,收藏36次。123_mybatisplus selectone

【android】android12蓝牙框架_android 蓝牙框架-程序员宅基地

文章浏览阅读1.6k次,点赞15次,收藏22次。参考:hl=zh-cnhl=zh-cnhl=zh-cn。_android 蓝牙框架

玩转X-CTR100 l STM32F4 l PS2无线手柄-4WD智能小车-程序员宅基地

文章浏览阅读388次。我造轮子,你造车,创客一起造起来!更多塔克创新资讯【塔克社区 www.xtark.cn 】【塔克博客 www.cnblogs.com/xtark/ 】 前面已介绍X-CTR100控制器解码PS2无线手柄,本文继续前文,使用PS2无线手柄,实现4WD智能小车的控制,实现两种控制模式,方向模式和坦克模式。 例程-PS2无线手柄-4WD智能小车(方向模式) 使用4个..._stm32-4wd智能小车摘要

(深度学习)基于残差卷积——resnet的水稻病害识别_resnet152-程序员宅基地

文章浏览阅读1.6k次,点赞20次,收藏34次。利用残差卷积神经网络Resnet152实现水稻病害识别,附带数据集和预训练模型下载链接,代码框架可套用于其它分类任务。_resnet152

Esp8266 进阶之路34 【外设篇③】乐鑫esp8266 NONOS SDK 3.0编程使用 SPI 驱动基于Max7219芯片的八位数码管,显示日期信息。(附带Demo)_8266时钟代码 数码管-程序员宅基地

文章浏览阅读7k次,点赞5次,收藏28次。本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。 1、 Esp8266之 搭建开发环境,开始一个“hellow world”串口打印。 2、 Esp8266之 利用GPIO开始使用按钮点亮你的“第一盏灯”。 3、 Esp8266之 利用 "软件定时器 " 定时0.5秒闪烁点亮一盏LED。4 、Es..._8266时钟代码 数码管