[NOIP2017 普及组] 棋盘——深搜 详解

2023-12-14 16:20
文章标签 详解 普及 棋盘 noip2017

本文主要是介绍[NOIP2017 普及组] 棋盘——深搜 详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目背景

NOIP2017 普及组 T3

题目描述

有一个 m×m 的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。

任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的), 你只能向上、下、左、右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 1 个金币。

另外, 你可以花费 2 个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用, 而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法; 只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。

现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?

输入格式

第一行包含两个正整数 m,n,以一个空格分开,分别代表棋盘的大小,棋盘上有颜色的格子的数量。

接下来的 n 行,每行三个正整数 x,y,c, 分别表示坐标为 (x,y) 的格子有颜色 c。

其中 c=1 代表黄色,c=0 代表红色。 相邻两个数之间用一个空格隔开。 棋盘左上角的坐标 (1,1),右下角的坐标为 (m,m)。

棋盘上其余的格子都是无色。保证棋盘的左上角,也就是 (1,1) 一定是有颜色的。

输出格式

一个整数,表示花费的金币的最小值,如果无法到达,输出 -1

输入输出样例

输入 #1

5 7
1 1 0
1 2 0
2 2 1
3 3 1
3 4 0
4 4 1
5 5 0

输出 #1

8

输入 #2

5 5
1 1 0
1 2 0
2 2 1
3 3 1
5 5 0

输出 #2

-1

说明/提示

样例 1 说明

棋盘的颜色如下表格所示,其中空白的部分表示无色。

从 (1,1) 开始,走到 (1,2) 不花费金币。

从 (1,2) 向下走到 (2,2) 花费 1 枚金币。

从 (2,2) 施展魔法,将 (2,3) 变为黄色,花费 2 枚金币。

从 (2,2) 走到 (2,3) 不花费金币。

从 (2,3) 走到 (3,3) 不花费金币。

从 (3,3) 走到 (3,4) 花费 1 枚金币。

从 (3,4) 走到 (4,4) 花费 1 枚金币。

从 (4,4) 施展魔法,将 (4,5) 变为黄色,花费 2 枚金币。

从 (4,4) 走到 (4,5) 不花费金币。

从 (4,5) 走到 (5,5) 花费 1 枚金币。

共花费 88 枚金币。

样例 2 说明

棋盘的颜色如下表格所示,其中空白的部分表示无色。

  

从 (1,1) 走到 (1,2),不花费金币。

从 (1,2) 走到 (2,2),花费 1 金币。

施展魔法将 (2,3) 变为黄色,并从 (2,2) 走到 (2,3) 花费 2 金币。

从 (2,3) 走到 (3,3) 不花费金币。

从 (3,3) 只能施展魔法到达 (3,2),(2,3),(3,4),(4,3)。

而从以上四点均无法到达 (5,5),故无法到达终点,输出−1。

数据规模与约定

对于 30% 的数据,1≤m≤5,1≤n≤10。

对于 60% 的数据,1≤m≤20,1≤n≤200。

对于 1100% 的数据,1≤m≤100,1≤n≤1,000。

分析

深度优先搜索算法

代码具体分析

1.头文件和命名空间

使用了万能头文件,包含了所有的标准库头文件,方便编写代码。

同时使用了命名空间std,避免了重名问题。

2.变量解释

二维数组a和v,分别表示迷宫的颜色和每个格子到起点的最小金币花费

dir数组,表示四个方向的移动

m和n,分别表示迷宫的大小和颜色变化的数量

ans,表示到达终点的最小金币花费,初始化为一个很大的数

3.深度优先搜索

这里使用了深度优先搜索算法

  • 从起点开始搜索,每次尝试往上下左右四个方向走到下一个格子。
  • 如果下一个格子是无色,则花费2个金币改变颜色;如果下一个格子是有色,则花费1个金币改变颜色
  • 如果颜色和上一个格子不同,则花费1个金币。
  • 如果下一个格子是终点,则判断最后一个格子的颜色是否和上一个格子的颜色不同,如果不同,则花费1个金币
  • 如果当前金币花费已经大于等于到达该格子的最小金币花费或者大于等于到达终点的最小金币花费,则剪枝。否则,更新到达该格子的最小金币花费,并继续搜索下一个格子。

4.主函数

首先输入迷宫的大小和颜色变化的数量,然后初始化a数组为-1,表示刚开始都是无色

初始化v数组为一个很大的数,表示到达每个格子的最小金币花费

接着输入每个格子的颜色,更新a数组

最后调用dfs函数,从起点开始搜索。如果到达终点的最小金币花费为一个很大的数,则输出-1,否则输出到达终点的最小金币花费

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N][N],v[N][N];
int dir[4][2]={-1,0,0,1,1,0,0,-1}; 
int m,n,ans=0x3f3f3f3f;
//搜索单元格是(x,y),从(1,1)到达(x,y)已用到的金币数量是val
//(x,y)的上一个单元格的颜色是c,(x,y)的上一单元是否使用了魔法 
void dfs(int x,int y,int val,int c,int mo){if(a[x][y]==-1&&mo) return;//不能连续使用魔法if(x==m&&y==m){//到达终点 if(a[m][m]!=c){//最后一个和上一个颜色不一样 val++;if(a[m][m]==-1) val++; } if(val<ans)  ans=val;return;} if(a[x][y]==-1){//无色 val+=2;mo=1; }else{//有色 mo=0;if(a[x][y]!=c){val+=1;c=a[x][y];}}//尝试往上下左右四个方向走到下一个格子 if(val>=v[x][y]||val>=ans){//剪枝 return;}else{v[x][y]=val;//记忆化 for(int i=0;i<4;i++){int xx=x+dir[i][0],yy=y+dir[i][1];if(xx>=1&&xx<=m&&yy>=1&&yy<=m)dfs(xx,yy,val,c,mo);}}
}
int main(){cin>>m>>n;memset(a,-1,sizeof a);//-1表示刚开始都是无色 memset(v,0x3f,sizeof v);int x,y,k;for(int i=1;i<=n;i++){cin>>x>>y>>k;a[x][y]=k;//(x,y)的颜色是k }dfs(1,1,0,a[1][1],0); if(ans==0x3f3f3f3f) cout<<-1;else cout<<ans;return 0;
}

这篇关于[NOIP2017 普及组] 棋盘——深搜 详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/493208

相关文章

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

springboot security快速使用示例详解

《springbootsecurity快速使用示例详解》:本文主要介绍springbootsecurity快速使用示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录创www.chinasem.cn建spring boot项目生成脚手架配置依赖接口示例代码项目结构启用s

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML