题目本体

题目描述

不难发现,豆豆能从很多事情中去思考数学,于是豆豆父母决定让他去练习射击,这是项需要集中注意力的运动,相信能够让豆豆暂时脱离数学。学习射击的第一天就让豆豆产生了浓厚的兴趣,射击的靶子是大饼圆,射击枪的子弹近似圆柱,为什么要圆的不能是其他的形状呢,于是豆豆开始构思,设计了这样一个好玩的问题:N*M 的方形格子靶子,每个格子有两种状态凸或者凹(如下图浅色表示凹,深色表示凸)

现在用一个十字横截面的子弹(填充黑色部分)去射击,被射中的小格子凹变凸,凸变凹,子弹放大后的横截面如下图

这种子弹最多可以覆盖 5 个格子,如图打完后,5 个格子凹凸状态发生了变化

请问最少需要几次射击使靶子中所有小格子都呈现凹的状态。
注意:子弹中心点如果打到四个角上则只会影响 3 个格子,如下图黑色格子表示被子弹中心点正好击中左上角后覆盖的 3 个格子,如果打到除四个角的边界上,则会影响到 4 个格子,如下图右侧的 4 个黑色格子所示,这是子弹中心点打中第 3 行第 6 列时的覆盖情况。(也就是说子弹超出靶子部分不起效)

输入

第一行两个用空格隔开的数字 N 和 M(1<=N,M<=17)
接下来 N 行描述靶子中小格子的状态,‘X’表示凸,‘.’表示凹。

输出

输出所需要的最少射击次数
注意:输入数据保证有解

样例输入1

5 5
XX.XX
X.X.X
.XXX.
X.X.X
XX.XX

样例输出1

5

样例输入2

8 9
…XXXXX…
.X…X.
X…X.X…X
X…X
X.X…X.X
X…XXX…X
.X…X.
…XXXXX…

样例输出2

25

解答部分

首先,显然子弹的射击顺序不影响最终的结果;结果只受如何选择弹位和该弹位上的射击次数有关。

其次,同个弹位只有射击0次1次两种可能。

射击两次与不射击完全相同,射击三次和射击一次完全相同,以此类推。

因此,如果我们规定了搜索的方向(比如从上到下且从左到右),那么就会有两个方向的格子(上和左)已被固定,选择好当前格子是否射击,再往后搜索的时候剩余的方向的格子(下和右)选择就会受限,这样就能进行大量的剪枝。

如果当前格子被确定为凸起,则剩余方向的格子不可同时射击或同时不射击
如果当前格子被确定为凹下,则剩余方向的格子必须同时射击或同时不射击

但这样复杂度还是不够低,还需进一步优化。

之前我们看问题的方式还是过于狭隘,只看到了其中一个点。
如果我们把一整行当成一个整体来考虑,并决定好第一行的射击方式后,我们就会发现第一行就会遗留下一个剩余状态第一行的初始状态 + 第一行的射击选择 所决定。
而由于第一行的射击方式已经确定,这个第一行的剩余状态又不能100%保证达成全凹,并且从第三行开始的所有射击均无法影响第一行的剩余状态,换句话说,如果我们要让第一行的最终状态变为全凹,只能依靠对第二行进行射击选择来完成,且这种选择有且只有一种

上一行的剩余状态为凹处,下一行同位置处必定不能射击
上一行的剩余状态为凸处,下一行同位置处必须进行射击

第一行的初始状态 + 第一行的射击选择 ) → 第一行的剩余状态第二行的射击选择

第二行的初始状态 + 第二行的射击选择 + 第一行的射击选择 ) → 第二行的剩余状态第三行的射击选择

第三行的初始状态 + 第三行的射击选择 + 第二行的射击选择 ) → 第三行的剩余状态第四行的射击选择
……(以此类推)

综上所述,我们只要枚举第一行如何进行射击,为了逐行完成全凹的目标,之后每行的选择就被固定,只需逐行进行模拟,对最后一行进行判定能否完成全凹的目标,并在枚举过程中不断记录最小值即可。
模拟过程可以手动模拟,也可以用位运算来进行。

代码部分

#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;typedef long long LL;const int MAXN=22;int Get_Effect(int,int&);int main()
{//cout<<(1<<-1)<<endl;//cout<<(59&31)<<endl;int n,m;char tmp;int mp[MAXN];memset(mp,0,sizeof(mp));cin>>n>>m;srand(10);for(int i=0; i<n; i++){for(int j=0; j<m; j++){bool rd=((rand()%2)==1);if(rd)tmp='X';else tmp='.';cout<<tmp<<" ";//cin>>tmp;mp[i]<<=1;mp[i]+=(tmp=='X');}cout<<endl;}//for(int i=0;i<n;i++)cout<<mp[i]<<endl;int ans=n*m;int mod=(1<<m)-1;for(int i=0; i<(1<<m); i++){int pre_choose=0;int now_choose=i;int effect;int cnt=0;for(int j=0; j<n; j++){effect=Get_Effect(now_choose,cnt)&mod;/*cout<<j+1;cout<<": pre_choose:"<<setw(3)<<pre_choose;cout<<" now_choose:"<<setw(3)<<now_choose;cout<<" effect:"<<setw(3)<<effect;cout<<" now_state:"<<setw(3)<<(mp[j]^pre_choose^effect);cout<<" mod:"<<setw(3)<<mod<<endl;*/int tmp=(mp[j]^pre_choose^effect);//cout<<"tmp:"<<tmp<<endl;pre_choose=now_choose; now_choose=tmp;}if(now_choose==0)cout<<"test:"<<hex<<i<<" "<<dec<<cnt<<endl;if(now_choose==0)ans=min(ans,cnt);}cout<<ans<<endl;return 0;
}int Get_Effect(int choose,int& cnt)
{int effect=0;for(int k=0; (1<<k)<=choose; k++){if((1<<k)&choose){effect^=(1<<(k-1));effect^=(1<<(k+0));effect^=(1<<(k+1));cnt++;}}return effect;
}

2016年第31届宁波市信息学竞赛复赛试题 D 射击相关推荐

  1. 绍兴市第十六届计算机复赛试题,绍兴市第十七届少儿信息学竞赛复赛试题

    绍兴市第十七届少儿信息学竞赛复赛试题 (考试时间:150分钟) 一.题目一览 中文题目名称 英文题目名称 输入文件名 输出文件名 每个测试点时限 测试点数目 每个测试点分值 听歌识曲 song son ...

  2. 沙盘游戏(2017绍兴市第十五届少儿信息学竞赛复赛试题)

    沙盘游戏 Ivy是如此地喜欢编程,以至于在面对游戏时也是如此.在沙盘游戏中有一个巨大的方形沙盘(长方形或者正方形),该沙盘被分隔成边长为1的小方格,每个小方格内有一个整数.沙盘玩家需要在沙盘中圈出一个 ...

  3. 2018年新生个人训练赛第十场(第29-30届宁波市信息学竞赛小学组)

    问题 A: 幸运数字III [ 提交][ 状态][ 讨论版] 题目描述 小李非常喜欢数字4和7,看到一个数字他就想快速计算出因子里面分别有几个4和7,但是智商捉急的他总是要算很久,喜欢编程的你能够帮助 ...

  4. 2022 年合肥市经开区第七届青少年信息学竞赛 小学组试题题解

    目录 第一题 车辆统计 第二题 直角三角形 第三题 质因数 第四题 采摘苹果 第一题 车辆统计

  5. 2022 年合肥市经开区第七届青少年信息学竞赛 小学组试题

    一.题目概况 二.注意事项 1.务必看清题目,严格按照所要求的格式输入.输出. 2.在调试程序时请先使用题目中的示例数据,然后再自行设计多组测试数据进行 调试. 3.每题一般有 10 个测试点,测试有 ...

  6. 2016年蜀山区第十五届青少年信息学竞赛

    2016年蜀山区第十五届青少年信息学竞赛 小学组试题 一.题目概况 题目名称 求差 生日 抓牛 工资 文件名

  7. 2016宁波计算机程序复赛,宁波第31届中小学生计算机程序设计竞赛复赛试题小学组.PDF...

    宁波第31届中小学生计算机程序设计竞赛复赛试题小学组 宁波市第31 届中小学生计算机程序设计竞赛复赛试题(小学组) 宁波市第31 届中小学生计算机程序设计竞赛 复赛试题(小学组) 比赛时间:2016 ...

  8. 第29届宁波市中小学生计算机程序设计竞赛复赛名单公布,宁波市第23届中小学生计算机程序设计竞赛复赛试题(小学组)...

    <宁波市第23届中小学生计算机程序设计竞赛复赛试题(小学组)>由会员分享,可在线阅读,更多相关<宁波市第23届中小学生计算机程序设计竞赛复赛试题(小学组)(7页珍藏版)>请在人 ...

  9. 合肥青少年信息学计算机竞赛试题,合肥市竞赛_27届合肥市信息学竞赛试题和答案_淘题吧...

    Ⅰ 合肥市第二十七届青少年信息学(计算机)竞赛小学组答案 动态规划? Ⅱ 合肥市化学竞赛 这个我不知道啊,不过我的经验是实验题多做一些好,一些物质的性质掌握些好,不知道会不会有分析题出现,我参加的福建 ...

最新文章

  1. caffe学习(五):cifar-10数据集训练及测试(Ubuntu)
  2. Java7 ConcurrentHashMap详解
  3. vmware14/15 安装Ubuntu12.04 图文八步法
  4. sql 取汉字首字母
  5. php open gl,Open GL 资料 01
  6. 位运算在一类数组题中的用法 只出现一次的数字I
  7. Ubuntu20.04更新源步骤
  8. 微信小程序之表单验证
  9. 白鸦:我印象中的Keso
  10. js混淆还原工具_技术分享:几种常见的JavaScript混淆和反混淆工具分析实战【转】...
  11. 人脸关键点检测face_landmark
  12. DOS命令的英文全称
  13. 学会这27种编程语言,你还怕找不到女朋友?!那是要几个有几个!
  14. 【Scrum模式语言15】发布计划(Release Plan)
  15. 2018年9月份面试小记
  16. linux开放端口的两种方法
  17. [指南]上海逛街大全
  18. java共享经济项目分享_共享创业项目平台哪个好(分享5个共享创业项目)
  19. H5缓存机制浅析-移动端Web加载性能优化【干货】
  20. 仪表放大器放大倍数分析-运算放大器

热门文章

  1. C++ opencv模板匹配
  2. python编程基础:快速微服务框架指南:flask:1: 简介与Hello World
  3. 关于markdown的licens
  4. 2016猴年春节有感,androidframework开发面试
  5. 2023基于微信小程序的婚庆婚纱摄影预约平台(SSM+mysql)-JAVA.VUE(论文+开题报告+运行)
  6. 对古人“一命二运三风水,四积德五读书”的人生命运总结的理解
  7. rust石头墙几个c4_290多种常用艺术贴图素材合集 Gumroad – Julio Sillet 3D Art – All Texture Packs ......
  8. 微信暗黑版7.0.10真的要来了!你会用吗?
  9. 集成电路领域核心会议与期刊
  10. javascript---window.createPopup