2020杭电多校 10C / HDU 6879 - Mine Sweeper (构造)
题意
定义《扫雷》游戏的地图中每个空白格子的值为其周围八个格子内地雷的数量(即游戏内临近地雷数量的提示)
则一张地图的值\(S\)为所有空白格子的值总和
现给定\(S\),要求构造出一张长度与宽度均不超过\(25\)的地图,使其值等于\(S\)
限制
\(1\leq T\leq 1001\)
\(0\leq S\leq 1000\)
思路
这题过的人数应该是最多的,所以肯定是存在比我的想法更优更方便的解的
但是题解写的不是很清楚,所以还是写下了这篇博客(画图好累……)
发现\(T_{max}=|S|\),范围内每个值肯定都会问一遍,考虑预处理所有方案(在线输出好像也没有问题的样子)
首先发现,如果一个地雷周围没有其他地雷,也没有障碍物(表示它不在图的边界上)
那么这个地雷对于答案的贡献就是\(8\)

考虑所有地雷都互不相邻的情况(一个地雷周围一圈不存在其他地雷)
由于图最大尺寸为\(25\times 25\)
地雷分布情况为\((2,2),(2,4),\dots,(2,24),(4,2),(4,4),\dots,(24,24)\)
这样总共能放置\(12\times 12=144\)个对答案贡献为\(8\)的地雷
由于\(144\times 8>1000\),这样的分布绰绰有余
所以得到一个结论:只要\(S\)为\(8\)的倍数,那么它一定有解
首先考虑\(S\lt 8\)的所有情况
当\(S=0\)时,直接输出一个\(1\times 1\)的空图即可
当\(S=1\)时

当\(S=2\)时

当\(S=3\)时

当\(S=4\)时

当\(S=5\)时

当\(S=6\)时

当\(S=7\)时

既然已经能够确定一个数的倍数一定有解了,那我们可以尝试找找看能否依托\(8\)来找出其他情况
也就是把\(S\geq 8\)的所有情况看成以下的形式之一表示
\begin{aligned}
8&k\\
8&k+1\\
8&k+2\\
8&k+3\\
8&k+4\\
8&k+5\\
8&k+6\\
8&k+7\\
\end{aligned}
\right \}
,\ k\in \Z
\]
对于\(S=8k+1\)的情况:
在\((1,1)\)的位置多放置一个地雷,可以使得原本位于\((2,2)\)的地雷对答案的贡献由\(8\)变成\(9\),且不影响其他地雷的贡献

对于\(S=8k+2\)的情况:
在\((1,1)\)与\((1,2)\)的位置多放置两个地雷,可以使得原本位于\((2,2)\)的地雷对答案的贡献由\(8\)变成\(10\),且不影响其他地雷的贡献

对于\(S=8k+3\)的情况:
在\((1,2)\)的位置多放置一个地雷,可以使得原本位于\((2,2)\)的地雷对答案的贡献由\(8\)变成\(11\),且不影响其他地雷的贡献

对于\(S=8k+4\)的情况:
在\((1,2)\)与\((2,1)\)的位置多放置两个地雷,可以使得原本位于\((2,2)\)的地雷对答案的贡献由\(8\)变成\(12\),且不影响其他地雷的贡献

对于\(S=8k+5\)的情况:
仅先看放置贡献为\(8\)的地雷,假设最后一个放置的地雷位于第\(i\)行
为了不影响它对答案的贡献,那么第\(i+1\)行不能放东西
由上面\(S=5\)的情况可得,我们可以将其上下倒置放在第\(i+2\)行,从而防止其对其他地雷贡献造成影响
(边界限制可行性证明在下面)

对于\(S=8k+6\)的情况:
参考\(S=6\),同样的,为了不产生冲突,只能放置在第\(i+2\)行

对于\(S=8k+7\)的情况:
由于\(S=7\)的情况里地雷需要占两行
所以要将\(S=7\)的情况倒置放在\(S=8k\)的第\(i+2\)行与第\(i+3\)行
(边界限制可行性证明在下面)

直接证明\(S=8k+7\)时需要用到\(i+3\)行的可行性情况吧
由于\(S\)最大为\(1000\),如果全部使用贡献为\(8\)的地雷方案填充地图,最多只需要\(125\)个地雷
每行最多能放置\(12\)个这种方案的地雷,那么最多只需要用到第\(11\)行过
对于原图,由于地雷在行之间也需要空一行,故\(i\)的最大值为\(22\)
\(22+3=25\),恰好满足题目要求,故方案可行
综上,本题所有\(S\)情况均有解,预处理后直接输出即可
注意,\(S=8k\)的情况最后也需要输出\(i+1\)行(最后一行空着,以保证有空格子让地雷做出贡献,即让最后一行的地雷非边界)
示例
如果没大看懂上面的例子,这里放几张截图领会一下大致意思即可








代码
(0ms~31ms/1000ms)
#include<bits/stdc++.h>
using namespace std;
int mp[1010][28][28];
int maxCol[1010];
void init()
{
    for(int i=8;i<=1000;i++)
    {
        int les=i/8,j,k;
        for(j=2;j<=24;j+=2)
        {
            for(k=2;k<=24;k+=2)
            {
                mp[i][j][k]=1;
                if(--les==0)
                    break;
            }
            if(les==0)
                break;
        }
        switch(i%8)
        {
            case 0:
                maxCol[i]=j+1;
                break;
            case 1:
                mp[i][1][1]=1;
                maxCol[i]=j+1;
                break;
            case 2:
                mp[i][1][1]=mp[i][1][2]=1;
                maxCol[i]=j+1;
                break;
            case 3:
                mp[i][1][2]=1;
                maxCol[i]=j+1;
                break;
            case 4:
                mp[i][1][2]=mp[i][2][1]=1;
                maxCol[i]=j+1;
                break;
            case 5:
                mp[i][j+2][2]=1;
                maxCol[i]=j+2;
                break;
            case 6:
                mp[i][j+2][1]=mp[i][j+2][2]=1;
                maxCol[i]=j+2;
                break;
            case 7:
                mp[i][j+3][1]=mp[i][j+3][2]=mp[i][j+2][1]=1;
                maxCol[i]=j+3;
                break;
        }
    }
}
int main()
{
    init();
    int T,S;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&S);
        if(S>=8)
        {
            printf("%d 25\n",maxCol[S]);
            for(int i=1;i<=maxCol[S];i++)
            {
                for(int j=1;j<=25;j++)
                {
                    if(mp[S][i][j])
                        putchar('X');
                    else
                        putchar('.');
                }
                putchar('\n');
            }
        }
        else if(S==0)
        {
            puts("1 1");
            puts(".");
        }
        else if(S==1)
        {
            puts("1 2");
            puts("X.");
        }
        else if(S==2)
        {
            puts("1 3");
            puts("X.X");
        }
        else if(S==3)
        {
            puts("2 2");
            puts("X.");
            puts("..");
        }
        else if(S==4)
        {
            puts("2 2");
            puts("X.");
            puts("X.");
        }
        else if(S==5)
        {
            puts("2 3");
            puts(".X.");
            puts("...");
        }
        else if(S==6)
        {
            puts("2 3");
            puts("XX.");
            puts("...");
        }
        else if(S==7)
        {
            puts("3 3");
            puts("XX.");
            puts("X..");
            puts("...");
        }
    }
    return 0;
}
												
											2020杭电多校 10C / HDU 6879 - Mine Sweeper (构造)的更多相关文章
- 2020杭电多校 C / HDU 6879 - Mine Sweeper
		
题意: t组输入,每组输入一个s 你需要输出一个r行c列的阵列,这个阵列中'X'代表炸弹,'.'表示没有炸弹 对于'.'这些位置都会有一个数值,这个值取决于这个位置附近8个位置,这8个位置一共有几个炸 ...
 - 【2020杭电多校】Distinct Sub-palindromes  找规律
		
题目链接:Distinct Sub-palindromes 题意: 给你一个长度n,你需要找出来一些串,这些串由A...Z和a...z构成.我们设长度为n的所有串中所包含回文子串最少的数量为ans.问 ...
 - 【2020杭电多校】 Lead of Wisdom、The Oculus
		
题目链接:Lead of Wisdom 题意:有n个物品,这些物品有k种类型.每种物品有对应的类型ti,其他值ai,bi,ci,di 你可以选择一些物品,但是这些物品要保证它们任意两者之间类型不能相同 ...
 - 【2020杭电多校】Total Eclipse 并查集+思维
		
题目链接:Total Eclipse 题意: t组输入,给你一个由n个点,m条边构成的图,每一个点的权值是ai.你每一次可以选择一批联通的点,然后让他们的权值都减去1.问最后把所有点的权值都变成0需要 ...
 - 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)
		
以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...
 - 2018 Multi-University Training Contest 1  杭电多校第一场
		
抱着可能杭电的多校1比牛客的多校1更恐怖的想法 看到三道签到题 幸福的都快哭出来了好吗 1001 Maximum Multiple(hdoj 6298) 链接:http://acm.hdu.edu. ...
 - HDU 4941 Magical Forest(map映射+二分查找)杭电多校训练赛第七场1007
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4941 解题报告:给你一个n*m的矩阵,矩阵的一些方格中有水果,每个水果有一个能量值,现在有三种操作,第 ...
 - HDU 4902 Nice boat  2014杭电多校训练赛第四场F题(线段树区间更新)
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...
 - HDU 5821 Ball (贪心排序) -2016杭电多校联合第8场
		
题目:传送门. 题意:T组数据,每组给定一个n一个m,在给定两个长度为n的数组a和b,再给定m次操作,每次给定l和r,每次可以把[l,r]的数进行任意调换位置,问能否在转换后使得a数组变成b数组. 题 ...
 
随机推荐
- 一条查询SQl是怎样执行的
			
MySQL的逻辑架构图 大体来说,MySQL可以分为Server层和存储引擎层两部分. Server层包括连接器.查询缓存.分析器,优化器等,涵盖MySQL的大多核心服务功能,以及所有的内置函数,存储 ...
 - MySQL的索引优化分析(二)
			
一.索引优化 1,单表索引优化 建表 CREATE TABLE IF NOT EXISTS article( id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO ...
 - 【Linux】salt的cmd.script命令介绍
			
salt是一个很棒的自动化运维工具之一,常用的有cmd.run,今天介绍的是cmd.script 其实一眼就能看出这个命令是执行脚本的命令 具体操作如下: 1.将/etc/salt/master中的 ...
 - 【Linux】服务器识别ntfs移动磁盘方法
			
Linux服务器无法识别ntfs磁盘 如果想识别的话,需要安装一个包ntfs-3g 安装好后,将移动磁盘插入到服务器的usb口中 新建一个目录,将磁盘挂载在新建的目录上 挂载命令如下: mount - ...
 - kubernets之pv以及pvc
			
一 持久卷以及持久卷声明的由来 由于不管是哪种卷,开发者都需要提前预知kubernets集群里面的存储类型,这样就在一定程度上违背了kubernets集群的设计理念,kubernets的设计理念是在由 ...
 - Java-Servlet知识总结
			
目录 Servlet概述 为什么要学习Servlet 什么是 Servlet 工作流程 生命周期 处理请求的方法 HttpServletRequest 和 HttpServletResponse Ht ...
 - JVM重新认识(一)oop-klass模型--HSDB使用验证
			
一:oop-kclass模型 思考:我们平时写的java类编译成.class文件,JVM加载.class文件,那么加载.class文件之后在JVM中就是oop-kclass(C++)模型形式存在的. ...
 - 全栈性能测试修炼宝典-JMeter实战笔记(三)
			
JMeter体系结构 简介 JMeter是一款开源桌面应用软件,可用来模拟用户负载来完成性能测试工作. JMeter体系结构 X1~X5是负载模拟的一个过程,使用这些组件来完成负载的模拟 Y1:包含的 ...
 - 提取当前文件夹下的所有文件名.bat(Windows批处理文件)
			
@echo off dir /s/b *.* > 文件名.txt exit
 - 浅析Linux进程空间布局
			
一.进程空间分布概述 对于一个进程,其空间分布如下图所示: 1.参数说明 程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码. 初始化过的数据(Data):在程序运行初已经对变量进行初 ...