前言

欢迎关注我(小周猪猪)的博客,同时也欢迎关注为你们讲解的乔治大佬(心畅)的博客。如果对于原来的考试,你有不会的题,可以参考数字游戏题解,搜索题解,递归地推题解或者更多讲课内容的笔记与讲解。


1.奇怪的机器人

看到这些方阵的题,我们便自然可以联想到用搜索来解决。但是实际上这道题可以同时用 DFS D F S DFS和 BFS B F S BFS来解决,这里采用较为简洁的 DFS D F S DFS+剪枝(记忆化)的做法。

深搜的基本步骤:如果我们用 DFS D F S DFS,那么在递归的过程中我们可以用4个参数来记录当前走到的行,列和总花费。如果上一个状态是边界,那么直接判断答案是否合法,再退出即可。否则再在当前状态的基础上,往上下左右四个方向走,如果可以走,那么就往下一个状态进行转移。

你可以认为上述内容属于废话,因为许多棋盘上的题都是用这种思路来做的。涉及到上下左右,我们便可以用方位数组简便程序(在程序中用 dx d x dx和 dy d y dy表示),也用方位数组记录行走的花费(用数组 cost c o s t cost表示)

但是你也可以知道,按照上述会出现大量非最优解,重复或多余的运算,我们可以考虑剪枝。

1 1 1.如果参数的状态相同,我们可以退出。用vis" role="presentation">visvisvis数组判断重复。
2 2 2.如果当前花费比上一次到达这一个点的花费还要不优的话,则退出。用F[i][j]" role="presentation">F[i][j]F[i][j]F[i][j]记录到 i i i,j" role="presentation">jjj的最优花费

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int stx,sty;
int finx,finy;
int F[100][100];
int ans=pow(10,9);
char Map[100][100];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int Cost[4]={1,2,3,4};
int vis[100][100][2000];
inline bool check(int X,int Y)
{return X>=1&&X<=n&&Y>=1&&Y<=m;
}//判断坐标(X,Y)是否超出地图范围
void dfs(int x,int y,int sum)
{if (sum>=F[x][y]&&F[x][y]>0) return;if (vis[x][y][sum]==1) return;//剪枝F[x][y]=sum;vis[x][y][sum]=1;if (x==finx&&y==finy){ans=min(ans,sum);return;}//边界for (int i=0;i<4;i++){int nextx=x+dx[i];int nexty=y+dy[i];if (check(nextx,nexty)==true)if (Map[nextx][nexty]=='.')dfs(nextx,nexty,sum+Cost[i]);}//进一步搜索return;
}
int main()
{freopen("robot.in","r",stdin);freopen("robot.out","w",stdout);cin>>n>>m;for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)cin>>Map[i][j];cin>>stx>>sty>>finx>>finy;dfs(stx,sty,0);if (ans==pow(10,9)) cout<<-1;else cout<<ans;fclose(stdin);fclose(stdout);return 0;
}

单词方阵

这是一道简单的枚举,然后按照题意去模拟即可:枚举每一个字符串“ yizhong y i z h o n g yizhong”中起点” y y y”的位置,然后向八个方向搜索即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
string s=" izhong";
char a[200][200];
int vis[200][200];
int dx[9]={0,-1,1,0,0,1,1,-1,-1};
int dy[9]={0,0,0,-1,1,1,-1,1,-1};
void f(int x,int y,int num)
{int stx=x,sty=y,flag=1;for (int i=1;i<=6;i++){x+=dx[num];y+=dy[num];if (a[x][y]!=s[i]) {flag=0;break;}}//判断该方向是否合法if (flag){for (int i=1;i<=6;i++){vis[stx][sty]=1;stx+=dx[num];sty+=dy[num];}vis[stx][sty]=1;}//如果合法则进行标记以便于最终输出结果
}
void find(int i,int j)
{if (i-6>=1) f(i,j,1);if (i+6<=n) f(i,j,2);if (j-6>=1) f(i,j,3);if (j+6<=n) f(i,j,4);if (i+6<=n&&j+6<=n) f(i,j,5);if (i+6<=n&&j-6>=1) f(i,j,6);if (i-6>=1&&j+6<=n) f(i,j,7);if (i-6>=1&&j-6>=1) f(i,j,8);//若条件合法,枚举8个方向return;
}
int main()
{freopen("dcfz.in","r",stdin);freopen("dcfz.out","w",stdout);cin>>n;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)cin>>a[i][j];for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if (a[i][j]=='y')find(i,j);//枚举yfor (int i=1;i<=n;i++){for (int j=1;j<=n;j++)if (vis[i][j]) cout<<a[i][j];else cout<<'*';cout<<endl;}fclose(stdin);fclose(stdout);return 0;
}

修复线路

这道题目一般难就难在如何想到怎么去建图,建图之后跑一遍最短路就完事了。

最后的答案问我们自己修复的最长线路的最小值,其实就是海亮有很多种不同的修剪方案,在这个自己修建的方案中有一个自己修剪的最大长度,现在就要求这个线路最小。相信对于”最大“”最小“的字眼你一定知道的是二分答案

我们暂且不管二分答案,我们知道海亮有一条自己修建的最大线路len" role="presentation">lenlenlen,其实就说明了自己修剪的每一条线路的长度都 ≤len ≤ l e n ≤len,只要小于这个数值修多少条线路都是没有问题的。那么,为了保证条件可以满足,我们必须让海亮修建的每一条线路都 ≤ ≤ ≤这个数,保险公司修的都>" role="presentation">>>>这个数(显然这种情况是成立的)。但是保险公司修的线路都是有限制的,所以我们希望保险公司修的线路越小越好。那么关键就是,如何知道这个保险公司修复的最小线路呢?

我们可以考虑用图论的算法解决,将任何一个大于 len l e n len的边都设为 1 1 1,否则设为0" role="presentation">000.不存在边则设置为 +∞ + ∞ +∞,跑一遍最短路,最后的结果就是保险公司要修剪的道路。为什么?因为路都是由 0 0 0和1" role="presentation">111组成的, 0 0 0表示不用修,1" role="presentation">111表示要修,那么最后的答案就是由很多个 1 1 1组成,便是需要保险公司修剪的道路的条数ans" role="presentation">ansansans。如何判断答案是否合法,只要 ans≤k a n s ≤ k ans≤k即可。——这就是 check c h e c k check函数的构成。

至于边是多少,二分答案即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int Len;
int n,p,k;
int Vis[1200];
int dis[1200];
int a[1200][1200];
int Map[1200][1200];
inline void Fillchar()
{memset(Vis,0,sizeof(Vis));memset(Map,100,sizeof(Map));memset(dis,100,sizeof(dis));
}
inline void Makemap()
{for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if (a[i][j]<a[0][0])Map[i][j]=(int)a[i][j]>Len;dis[1]=0;Vis[1]=0;for (int i=2;i<=n;i++) dis[i]=Map[1][i]; return;
}//建图
inline void Error()
{cout<<"-1\n";exit(0);
}
int Shortest_Path()
{for (int now=1;now<=n;now++){int Min=a[0][0],pnt=0;for (int i=1;i<=n;i++)if (!Vis[i] && dis[i]<Min)Min=dis[i] , pnt=i;if (Min==a[0][0] || !pnt) break;else Vis[pnt]=1;for (int i=1;i<=n;i++)if (!Vis[i] && dis[pnt]+Map[pnt][i]<dis[i])dis[i]=dis[pnt]+Map[pnt][i];}return dis[n];
}//采用无堆优化且邻接矩阵存储的迪杰斯特拉算法
bool Check()
{int ans;Fillchar();Makemap();ans=Shortest_Path();return ans<=k;
}//二分答案的验证函数
int main()
{cin>>n>>p>>k;memset(a,100,sizeof(a));for (int i=1;i<=p;i++){int x,y,v;cin>>x>>y>>v;a[x][y]=a[y][x]=v;}//邻接矩阵构建无向图 int Left=0,Right=a[0][0];while (Left+1<Right){Len=(Left+Right)>>1;if (Check()==true) Right=Len;else Left=Len;if (Len<=0) Error();}Len=Left;if (Check()) cout<<Left<<"\n";else cout<<Right<<"\n";//二分答案修建最大路径长度 return 0;
}

后记

关注猪猪的博客,我们一起交流哦~
同时欢迎对猪猪的博客进行点赞,评价,指正和访问哦~

【考题 题解】奇怪机器人单词方阵修建道路相关推荐

  1. 洛谷—题解 P1101 单词方阵

    原题链接P1101 单词方阵 有条件的小伙伴可以点进原网站开题,也可直接看我下面的截图 废话一堆  艾瑞巴蒂,我可爱的小伙伴们!我也是很久没有写题解了,因为疫情的关系,在家我TM实在太闲了-做做题,写 ...

  2. P1101 单词方阵

    P1101 单词方阵 https://www.luogu.org/problemnew/show/P1101 标签 难度 普及- 时空限制 1000ms / 128MB 提示:收藏到任务计划后,可在首 ...

  3. [BZOJ1626][Usaco2007 Dec]Building Roads 修建道路

    1626: [Usaco2007 Dec]Building Roads 修建道路 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1730  Solved ...

  4. 7-14 修建道路 (10 分)

    7-14 修建道路 (10 分) N个村庄,从1到N编号,现在请您兴建一些路使得任何两个村庄彼此连通.我们称村庄A和B是连通的,当且仅当在A和B之间存在一条路,或者存在一个存在C,使得A和C之间有一条 ...

  5. bzoj 1626: [Usaco2007 Dec]Building Roads 修建道路(最小生成树)

    1626: [Usaco2007 Dec]Building Roads 修建道路 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1709  Solved ...

  6. 枚举求解单词方阵(洛谷P1101题题解,Java语言描述)

    题目要求 P1101题目链接 分析 可以用DFS做,但我立下了个Flag,所以就用了朴素的枚举来做.... 结果,我的天哪,做了好几个小时-- 其实这种地图题,真的适合 DFS or BFS or D ...

  7. 洛谷——P1101 单词方阵

    题目描述 给一n \times nn×n的字母方阵,内可能蕴含多个"yizhong"单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着 88 个方向的任一方向,同一单词摆放时不 ...

  8. P1101 单词方阵(DFS)

    题目描述 给一n \times nn×n的字母方阵,内可能蕴含多个"yizhong"单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着 88个方向的任一方向,同一单词摆放时不再 ...

  9. 洛谷 P1101 单词方阵

    给一n×n的字母方阵,内可能蕴含多个"yizhong"单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着 8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉 ...

最新文章

  1. pandas学习之Series结构
  2. python做测试书籍推荐_学习pytest应该观看的书籍?
  3. The FBX plug-in does not support objects set to By Object mode in the Object Properties Display
  4. python KeyError: 4
  5. struct 模块 把一个类型,如数字,转成固定长度的bytes
  6. 学习笔记Flink(五)—— Flink开发环境配置及运行实例(单词计数)
  7. Synchronize对象锁
  8. linux fedora35安装Pantheon桌面环境命令整理
  9. 如何在SAP Cloud for Customer的Silverlight UI中找到后台错误的明细
  10. idea测试连接mysql报错08001_IDEA连接MySQL(版本8)数据库失败的解决方法(报错08001)...
  11. 【Python第三篇】Python装饰器、生成器、迭代器
  12. 微信 的微服务器配置,spring-boot wm-accesstoken
  13. python图像转字符画_Python实现图片转字符画的示例
  14. shell基本理论知识
  15. 不用下载Axure RP Extension for Chrome插件,即可看原型文件
  16. Linux网络管理实战2-组建局域网
  17. mac怎么无线打印机连接到服务器,Mac如何连接打印机-Mac连接打印机教程 - 河东软件园...
  18. DIY 1U硬件防火墙实录
  19. 技术革命才是真正的革命
  20. 【文本分析】基于粤港澳大湾区博物馆访客评价的文本分析

热门文章

  1. WebRTC[44] - WebRTC 在安卓端的视频硬编硬解策略详解
  2. bootstrap table排序php,BootStrap+Table排序分页序号
  3. b站视频上传软件操作视频教程
  4. 区块链倪老师:写给区块链初创者的一封信(二)
  5. 蒙版Android指引蒙版效果
  6. 拯救者r9000p ubuntu重装记录
  7. 小米笔记本 Pro 14 2021怎么样?测评值得买吗?详细性能点评
  8. php和Java哪个好?php和Java的对比
  9. xXx时间屏保3.6
  10. iOS音频播放编程简介