热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:棋盘(BFS)

本文由编程笔记#小编为大家整理,主要介绍了棋盘(BFS)相关的知识,希望对你有一定的参考价值。原题:
本文由编程笔记#小编为大家整理,主要介绍了棋盘(BFS)相关的知识,希望对你有一定的参考价值。

原题:


1956: 棋盘(chess)


时间限制: 1 Sec  内存限制: 256 MB




题目描述




有一个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, 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 枚金币

共花费 8 枚金币。

 





输出




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

 

样例2输入

5 5

1 1 0

1 2 0

2 2 1

3 3 1

5 5 0

样例2输出:

-1

输入输出样例 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





样例输入 Copy



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





样例输出 Copy



8





数据范围




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

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

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

 

 





 ~~本蒟蒻第一次写题解,写的不好多多包涵~~
    这是一道很明显的搜索题,最近几天在练BFS的题目,所以讲讲BFS解题思路,大佬勿喷
题意:
    在一个m*m的棋盘中,从(1,1)出发到(m,m),上下左右移动,移动到同色格子不需要代价,移动到不同色格子需要代价为1,不能移动到无色格子但可以花费代价2将无色格子变为有色格子,**不能从无色格子移动到另一无色格子**

首先考虑从一个格子走到另一个格子有哪些情况
(方便起见将红色设为1,黄色设为2,无色设为0):

1. 从有色格子走到同一有色格子(1->1或2->2)
2. 从有色格子走到不同色的有色格子(1->2或2->1)
3. 从有色格子走到无色格子(此时需要使用魔法)(1->0或2->0)
4. 从施了魔法的无色格子移动到有色格子(还需考虑魔法将无色格子变成了什么颜色)(0->1或0->2)

 



接着考虑搜索到一个可走的点时需要将哪些元素压入队列,用一个结构体捆绑

1 struct node
2 {
3 int x,y,c,s,p;
4 }now;

 

其中x,y表示加入队列的点的坐标(x,y),c记录该点原本的颜色,s记录该点施了魔法后的颜色(若该点原本有色则s仍为原本的颜色),p记录目前所需的代价。

因为本题需要的是代价最小而不是步数,所以最先搜索到的点不一定是代价最小的点,再建一个v数组统计所有可能的代价。

套入BFS的模板,代码如下:

 

1 #include<iostream>
2 #include
3 #include
4 using namespace std;
5 int n,m,ans,tot,mark[1005][1005],map[1005][1005],v[5005];
6 //tot统计所有可能的代价
7 //mark记录到各个点的最小代价
8 //map记录棋盘初始状况
9 //v记录到达终点的所有可能的代价
10 int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
11 //用dx,dy两个数组控制移动方向
12 struct node
13 {
14 int x,y,c,s,p;
15 }now;
16 queue q;//STL库自带的队列
17 //听说速度会比手打队列慢一点,但应该关系不大
18 void bfs(int x,int y)
19 {
20 mark[x][y]=0;//起点不需要代价
21 q.push({x,y,map[x][y],map[x][y],0});
22 while(!q.empty())
23 {
24 now=q.front();
25 q.pop();//出队
26 x=now.x,y=now.y;
27 int c=now.c,p=now.p,s=now.s;
28 if(x==m && y==m) v[++tot]=p;//找到一个解就存入v数组
29 for(int i=0;i<4;i++)
30 {
31 int tx=x+dx[i],ty=y+dy[i];
32 if(tx>=1 && tx<=m && ty>=1 && ty<=m)
33 {//判断是否越界
34 if(map[x][y]!=0 && map[x][y]==map[tx][ty] && mark[tx][ty]>p)
35 {
36 mark[tx][ty]=p;//如果可以得到更小代价就更新,下同
37 q.push({tx,ty,map[tx][ty],map[tx][ty],p});//入队
38 }
39 //第一种情况
40 else if(map[x][y]!=0 && map[tx][ty]!=0 && map[x][y]!=map[tx][ty] && mark[tx][ty]>p+1)
41 {
42 mark[tx][ty]=p+1;
43 q.push({tx,ty,map[tx][ty],map[tx][ty],p+1});
44 }
45 //第二种情况
46 else if(map[x][y]!=0 && map[tx][ty]==0 && mark[tx][ty]>p+2)
47 {
48 mark[tx][ty]=p+2;
49 q.push({tx,ty,map[tx][ty],map[x][y],p+2});
50 //注意,这种情况需要使用一次魔法,此时s记录为未移动前的格子的颜色
51 }
52 //第三种情况
53 else if(map[x][y]==0 && map[tx][ty]==s && mark[tx][ty]>p)
54 {
55 mark[tx][ty]=p;
56 q.push({tx,ty,mark[tx][ty],mark[tx][ty],p});
57 }
58 //第四种情况(1)
59 else if(map[x][y]==0 && map[tx][ty] && map[tx][ty]!=s && mark[tx][ty]>p+1)
60 {
61 mark[tx][ty]=p+1;
62 q.push({tx,ty,mark[tx][ty],mark[tx][ty],p+1});
63 }
64 //第四种情况(2)
65 //如果这几种情况都不符合,只剩下从无色格子到无色格子一种可能,不需考虑
66 }
67 }
68 }
69 return;
70 }
71 int main()
72 {
73 scanf("%d %d",&m,&n);
74 for(int i=1;i<=m;i++)
75 for(int j=1;j<=m;j++) mark[i][j]=0x7fffffff;
76 //将到达各个点的最小代价初始化为无穷大(0x7fffffff)
77 for(int i=1;i<=n;i++)
78 {
79 int a,b,cl;
80 scanf("%d %d %d",&a,&b,&cl);
81 map[a][b]=cl+1;//将红色记为1,黄色记为2,无色则为0
82 }
83 bfs(1,1);
84 if(!tot) { printf("-1"); return 0; }//如果没有解,输出-1
85 ans=v[1];
86 for(int i=2;i<=tot;i++) ans=min(ans,v[i]);
87 //比较并求出最小代价
88 printf("%d",ans);
89 return 0;
90 }

 


推荐阅读
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
author-avatar
瓶子2502854683
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有