Codeforce s Round 920 (Div. 3) G题 旋转矩阵,斜缀和,平移

Problem - G - Codeforces

目录

题意:

思路:

总思路:

旋转矩阵:

前缀和预处理:

平移的处理,尤其是越界的处理:

核心代码:


题意:

给你个n*m的矩阵,里面要么是目标' # ',要么是空的' . '。

还有值k,代表这样的范围:

我们有四个方向可选。图中黑点即是我们落脚点,可以随意选,要使黑色区域的目标'#'最多,输出这个最大值

思路:

总思路:

‘#’是随机给的,我们只能暴力。暴力上做优化即可。

如果这四种都做,代码是类同但细节处理太多,而只用一种方向然后旋转矩阵这样是等价的。

我们选择第三种,使用前缀和(列缀和,斜缀合)方便:

由于面积可能很大,每个落脚点都数时间消耗太多。我们可以发现相邻的是平移过去的,只差一列和斜着一列:

所以我们对上次的‘#’数目,加上这列的'#'数目,再减去斜着的'#'数目,就是这次的'#'数目了。

预处理出前缀和,这样平移时加的减的都可以直接算出来。(越界的处理需要注意)

旋转矩阵:

(这个C语言OJ就写过。我好像有一次没写出来,然后就有了心理阴影,其实很好写)

我们再创个二维char数组next,把旋转的写进这个数组,然后覆盖原数组即可。

我们可以借助个例子去想,比如顺时针旋转:

1 2 3 4      5 1		
5 6 7 8	     6 2
	         7 3
	         8 4

我们可以发现第一行变成了倒数第一列,而原来的列数变成了新的行数。

所以next[ j ][ chars.size()-1-i ] = chars[ i ][ j ]        (chars就是原始图)

vector<vector<char>>next(chars[0].size(), vector<char>(chars.size()));
for (int i = 0; i < chars.size(); i++)
{
	for (int j = 0; j < chars[0].size(); j++)
	{
		next[j][chars.size()-1 - i] = chars[i][j];
	}
}
chars = next;

(注意新的图的n和m是变的。)

前缀和预处理:

可能没写过斜缀和。然后下标可以从1开始,我是写的从0开始的。

	int t = 4;
	while (t--)
	{
		n = chars.size(), m = chars[0].size();
		vector<vector<int>>narr(n, vector<int>(m)), rd(n, vector<int>(m));
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				if (i > 0)
					narr[i][j] = narr[i - 1][j] + (chars[i][j] == '#');
				else
					narr[i][j] = chars[i][j] == '#';
			}
		}
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				if(i>0&&j>0)
					rd[i][j] = rd[i - 1][j - 1] + (chars[i][j] == '#');
				else
					rd[i][j] = chars[i][j] == '#';
			}
		}

平移的处理,尤其是越界的处理:

for (int i = 0; i < n; i++)
{
	int tmp = narr[min(i + k, n - 1)][0] - (i - 1 >= 0 ? narr[i - 1][0] : 0);
	ans = max(ans, tmp);
	for (int j = 1; j < m; j++)//右平移
	{
		//x,y:前一个位置最下面那个点
		int x = i + k, y = j-1;
		if (x >= n)
		{
			y -= x - (n - 1);
			x = n - 1; 
		}
		tmp += narr[min(i+k,n-1)][j] - (i - 1 >= 0 ? narr[i - 1][j] : 0);
		if(y>=0)
		tmp	-= rd[x][y] - (j - 1 - k - 1 >= 0&&i-1>=0 ? rd[i - 1][j - 1 - k - 1] : 0);
		ans = max(ans, tmp);
	}
}

代码中x,y就是1点。

1的列缀合-2的列缀合就是新增的'#'

3的斜缀合-4的斜缀合就是失去的'#'

最难处理的就是3越界后的斜缀合:

我们可以发现,不管下面什么情况越界,最后一行都是n-1。我们取n-1对应着的斜缀合即可。

x,y仍代表1点(见上面),(x,y-1)就是原来的斜缀合的点,现在往左上角移动了,行的变换数是等于列的变换数的,而行变换(x-(n-1)),那么列也减去这个,即行为n-1,列为y-1 - (x-(n-1))。

其余的越界是好处理的,代码里有我的处理情况。

核心代码:

void solve()
{
	int n, m, k;
	cin >> n >> m >> k;
	vector<vector<char>>chars(n, vector<char>(m));
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			cin >> chars[i][j];

	int ans = 0;
	int t = 4;
	while (t--)
	{
		n = chars.size(), m = chars[0].size();
		vector<vector<int>>narr(n, vector<int>(m)), rd(n, vector<int>(m));
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				if (i > 0)
					narr[i][j] = narr[i - 1][j] + (chars[i][j] == '#');
				else
					narr[i][j] = chars[i][j] == '#';
			}
		}
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				if(i>0&&j>0)
					rd[i][j] = rd[i - 1][j - 1] + (chars[i][j] == '#');
				else
					rd[i][j] = chars[i][j] == '#';
			}
		}

		for (int i = 0; i < n; i++)
		{
			int tmp = narr[min(i + k, n - 1)][0] - (i - 1 >= 0 ? narr[i - 1][0] : 0);
			ans = max(ans, tmp);
			for (int j = 1; j < m; j++)//右平移
			{
				//x,y:前一个位置最下面那个点
				int x = i + k, y = j-1;
				if (x >= n)
				{
					y -= x - (n - 1);
					x = n - 1; 
				}
				tmp += narr[min(i+k,n-1)][j] - (i - 1 >= 0 ? narr[i - 1][j] : 0);
				if(y>=0)
				tmp	-= rd[x][y] - (j - 1 - k - 1 >= 0&&i-1>=0 ? rd[i - 1][j - 1 - k - 1] : 0);
				ans = max(ans, tmp);
			}
		}

		vector<vector<char>>next(chars[0].size(), vector<char>(chars.size()));
		for (int i = 0; i < chars.size(); i++)
		{
			for (int j = 0; j < chars[0].size(); j++)
			{
				next[j][chars.size()-1 - i] = chars[i][j];
			}
		}
		chars = next;
	}
	cout << ans << endl;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t; cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/330640.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【论文解读】用于代码处理的语言模型综述

目录 1.简要介绍 2.代码处理的语言模型的评估 3.通用语言模型 4.用于代码处理的特定语言模型 5.语言模型的代码特性 6.软件开发中的LLM 7.结论与挑战 ​​​​​​​1.简要介绍 在这项工作中&#xff0c;论文系统地回顾了在代码处理方面的最新进展&#xff0c;包括50个模…

Elasticsearch各种高级文档操作2

本文来记录下Elasticsearch各种文档操作 文章目录 初始化文档数据 初始化文档数据 在进行各种文档操作之前&#xff0c;我们先进行初始化文档数据的工作

【MySQL】权限控制

DCL-权限控制 查询权限 show grants for 用户名主机名;授予权限 grant 权限列表 on 数据库名.表名 to 用户名主机名;grant all on test.* to user%; %是通配符&#xff0c;表示任意主机。撤销权限 revoke 权限列表 on 数据库名.表名 from 用户名主机名;revoke all on test.*…

10- OpenCV:基本阈值操作(Threshold)

目录 1、图像阈值 2、阈值类型 3、代码演示 1、图像阈值 &#xff08;1&#xff09;图像阈值&#xff08;threshold&#xff09;含义&#xff1a;是将图像中的像素值划分为不同类别的一种处理方法。通过设定一个特定的阈值&#xff0c;将像素值与阈值进行比较&#xff0c;根…

【代码随想录07】344.反转字符串 541. 反转字符串II 05.替换空格 151.翻转字符串里的单词 55. 右旋转字符串

目录 344. 反转字符串题目描述做题思路参考代码 541. 反转字符串 II题目描述参考代码 05. 替换数字题目描述参考代码 151. 反转字符串中的单词题目描述参考代码 55. 右旋转字符串题目描述参考代码 344. 反转字符串 题目描述 编写一个函数&#xff0c;其作用是将输入的字符串反…

指向未来: 量子纠缠的本质是一个指针

指向未来: 量子纠缠的本质是一个指针 概述基本概念理解量子纠缠PythonJavaC 理解波粒二象性PythonJavaC 理解量子隧穿理解宇宙常量PythonJavaC 概述 量子纠缠 (Quantum Entanglement) 是量子系统重两个或多个粒子间的一种特殊连接, 这种连接使得即使相隔很远, 这些粒子的状态也…

Git怎么将文件夹上传至github,全过程

小白建议参考github文件上传全流程-新手入门系列&#xff08;超详细&#xff01;&#xff01;&#xff01;&#xff09; 中间可能会有报错 $ ssh -T gitgithub.com ssh: connect to host github.com port 22: Connection timed out 这时&#xff0c;参考&#xff0c;如何解决&a…

视频美颜SDK技术解析与技术对比

当下&#xff0c;各类应用和服务纷纷采用视频美颜SDK&#xff0c;以提供更加令人满意的视觉效果。本文将深入探讨视频美颜SDK的技术原理&#xff0c;同时对比不同SDK的特性&#xff0c;为开发者和决策者提供全面的技术参考。 一、技术原理解析 1.图像处理基础 视频美颜SDK基…

模具制造企业ERP系统有哪些?企业怎么选型适配的软件

模具的生产管理过程比较繁琐&#xff0c;涵盖接单报价、车间排期、班组负荷评估、库存盘点、材料采购、供应商选择、工艺流转、品质检验等诸多环节。 有些采用传统管理手段的模具制造企业存在各业务数据传递不畅、信息滞后、不能及时掌握订单和车间生产情况&#xff0c;难以对…

阿里云云原生助力安永创新驱动力实践探索

云原生正在成为新质生产力变革的核心要素和企业创新的数字基础设施。2023 年 12 月 1 日&#xff0c;由中国信通院举办的“2023 云原生产业大会”在北京召开。在大会“阿里云云原生”专场&#xff0c;安永科技咨询合伙人王祺分享了对云原生市场的总览及趋势洞见&#xff0c;及安…

Unity之四元数

欧拉角 万向节死锁 四元数是什么 Unity中四元数的初始化 四元数和欧拉角的互相转换 补充 四元数相乘代表旋转四元数

基于SpringBoot的民宿预定管理系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用例设计2.2 功能设计2.2.1 租客角色2.2.2 房主角色2.2.3 系统管理员角色 三、系统展示四、核心代码4.1 查询民宿4.2 新增民宿4.3 新增民宿评价4.4 查询留言4.5 新增民宿订单 五、免责说明 一、摘要 1.1 项目介绍 基于…

6款文章改写神器免费修改文章效果好

文章写作对于很多人来说&#xff0c;写作并不是一件轻松的事情。尤其是在需要频繁产出大量文章的时候&#xff0c;如何保持文章的原创性和质量就成了一个挑战。但是方法还是有的&#xff0c;如今许多免费的文章改写神器可以通过改写文章的方式生成全新的原创文章&#xff0c;从…

MyBatis-Plus的进阶:乐观锁和悲观锁、逻辑删除、分页和查询构造器

目录 1.乐观锁和悲观锁 1.1.什么是乐观锁和悲观锁 1.2.乐观锁和悲观锁的区别 1.3.综合案例 2.逻辑删除 2.1.什么是逻辑删除 2.2.为什么使用逻辑删除 2.3.综合案例 2.3.1.官方提示 2.3.2.配置方式 2.3.3.案例演示 3.分页和查询构造器 3.1.查询构造器 3.2.分页 1.乐…

YOLOv5改进 | 检测头篇 | 利用DynamicHead增加辅助检测头进行针对性检测(让小目标无所遁形)

一、本文介绍 本文给大家带来的改进机制是针对性的改进,针对于小目标检测增加P2层,利用DynamicHead(原版本一比一复现,全网独一份,不同于网上魔改版本)进行检测,其中我们增加P2层其拥有更高的分辨率,这使得模型能够更好地捕捉到小尺寸目标的细节。在这些的基础上配合Dyn…

一、Flask学习之HTML

一、Flask学习之HTML 1.运行简单页面 首先需要搭建环境&#xff1a; pip install flaskfrom flask import Flaskapp Flask(__name__)# 创建了网址 /show/info 和函数index之间的对应关系&#xff0c;以后用户在浏览器上访问/show/info&#xff0c;网站自动执行index函数 ap…

npm超详细安装(包括配置环境变量)!!!npm安装教程(node.js安装教程)

安装node.js:(建议选择相对低一点的版本&#xff0c;相对稳定)​下载完成直接点击next即可(安装过程中会直接添加path的系统变量&#xff0c;变量值是自己的安装路径&#xff0c;可自行选择&#xff0c;比如&#xff1a;D:\software\)​安装完成:winR打开电脑控制台&#xff0c…

python依赖安装、执行、打包

python依赖安装、执行、编译打包 本文介绍python项目的依赖安装、执行、以及使用pyinstaller编译打包成可执行文件的命令。 python项目执行部署有两种方式&#xff0c;具体步骤&#xff1a; 一、python环境安装 --> 安装pip --> 依赖包安装 --> 执行python程序 二、使…

操作系统课程设计-Linux 进程间通信

目录 前言 1 实验题目 2 实验目的 3 实验内容 3.1 步骤 3.2 关键代码 3.2.1 Server和Client的创建 3.2.2 Server核心代码 3.2.3 Server核心代码 4 实验结果与分析 5 代码 前言 本实验为课设内容&#xff0c;博客内容为部分报告内容&#xff0c;仅为大家提供参考&…

如何在CentOS下使用Docker部署Halo博客网站并结合内网穿透远程访问

文章目录 ⛳️ 推荐1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤&#xff1a;1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 ⛳️ 推荐 前些天发现了…