news 2026/10/27 18:36:02

UVa 767 Game

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 767 Game

题目描述

一个孩子绘制了NNN(N≤100N \le 100N≤100)个带编号的彩色圆圈。他用彩色有向线段连接了其中一些圆圈。任意一对圆圈之间可以存在多条不同颜色的线段。每种颜色(无论是圆圈颜色还是线段颜色)都被赋予一个不超过100100100的正整数。

游戏开始时,孩子首先选择三个互不相同的整数LLL、KKK、QQQ(均在111到NNN之间)。然后他在圆圈LLL中放置一个棋子,在圆圈KKK中放置另一个棋子,随后按照以下规则移动:

  • 棋子只能沿线段方向移动;
  • 若要将一个棋子沿某条线段移动,则该线段的颜色必须与另一个棋子所在圆圈的颜色相同;
  • 两个棋子不能同时位于同一个圆圈;
  • 移动顺序自由(可以连续移动同一个棋子);
  • 当任意一个棋子到达圆圈QQQ时,游戏立即结束。

要求计算使游戏结束所需的最少移动次数,如果无法结束则报告无解。

输入格式

第一行包含一个整数,表示数据集的个数。该行后有一个空行。
每个数据集的第一行包含四个整数N,L,K,QN, L, K, QN,L,K,Q。
第二行包含NNN个整数c1,c2,…,cNc_1, c_2, \dots, c_Nc1​,c2​,…,cN​,表示圆圈111到NNN的颜色。
第三行包含一个整数MMM(0≤M≤100000 \le M \le 100000≤M≤10000),表示线段总数。
接下来MMM行,每行描述一条有向线段,包含三个整数Aj,Bj,CjA_j, B_j, C_jAj​,Bj​,Cj​,表示从AjA_jAj​到BjB_jBj​的线段,颜色为CjC_jCj​。

数据集之间用一个空行分隔。

输出格式

对于每个测试用例,第一行输出YES(如果游戏可以结束)或NO(否则)。
若答案为YES,第二行输出一个整数 —— 最少移动次数。
相邻测试用例的输出之间打印一个空行。

样例

样例输入

1 5 3 4 1 2 3 2 1 4 8 2 1 2 4 1 5 4 5 2 5 1 3 3 2 2 3 2 4 5 3 1 3 5 1

样例输出

YES 3

题目分析

本题是一个双棋子状态空间搜索问题。两个棋子的位置共同构成一个状态(x,y)(x, y)(x,y),其中xxx和yyy分别是两个棋子所在的圆圈编号,且必须满足x≠yx \ne yx=y。初始状态为(L,K)(L, K)(L,K),目标状态为任意一个棋子到达QQQ,即x=Qx = Qx=Q或y=Qy = Qy=Q。每次移动选择一个棋子,将其沿一条有向边移动到新位置,移动的合法性取决于另一个棋子所在圆圈的颜色与该边颜色是否相同,并且移动后两个棋子不能重合。

因为每次移动的代价均为111,所以问题转化为在状态图上求从初始状态到任意目标状态的最短路径长度。状态总数最多为N×(N−1)≤9900N \times (N-1) \le 9900N×(N−1)≤9900,每个状态可转移的边数依赖于两个棋子的出边数量,总边数M≤10000M \le 10000M≤10000,因此使用广度优先搜索(BFS\texttt{BFS}BFS)可以在有限时间内得到答案。

解题思路

状态表示与转移

设dist[x][y]\textit{dist}[x][y]dist[x][y]表示到达状态(x,y)(x, y)(x,y)所需的最少移动次数,初始dist[L][K]=0\textit{dist}[L][K] = 0dist[L][K]=0。使用队列进行BFS\texttt{BFS}BFS。

对于当前状态(u,v)(u, v)(u,v),尝试移动第一个棋子(位于uuu):

  • 遍历所有从uuu出发的边(u→nxt)(u \to nxt)(u→nxt),颜色为colcolcol。
  • 若colcolcol等于另一个棋子所在圆圈vvv的颜色circleColor[v]\textit{circleColor}[v]circleColor[v],并且nxt≠vnxt \ne vnxt=v,则移动合法。
  • 如果nxt=Qnxt = Qnxt=Q,则游戏结束,当前步数加111即为答案。
  • 否则若dist[nxt][v]\textit{dist}[nxt][v]dist[nxt][v]未访问,则更新并入队。

同理,移动第二个棋子(位于vvv)时,需要检查颜色是否等于circleColor[u]\textit{circleColor}[u]circleColor[u],且nxt≠unxt \ne unxt=u,并判断是否到达QQQ。

算法流程

  1. 读入数据集。
  2. 存储圆圈颜色数组circleColor[1..N]\textit{circleColor}[1..N]circleColor[1..N]。
  3. 建立邻接表adj[u]\textit{adj}[u]adj[u],存储从uuu出发的所有边(目标顶点,颜色)。
  4. 初始化dist\textit{dist}dist为−1-1−1,队列qqq。
  5. 将(L,K)(L, K)(L,K)入队,dist[L][K]=0\textit{dist}[L][K] = 0dist[L][K]=0。
  6. 不断出队,按上述规则扩展状态,直至队列为空或找到目标。
  7. 若找到目标,返回步数;否则返回−1-1−1。
  8. 根据返回值输出YES/NO及步数,注意数据集间空行。

复杂度分析

状态数为O(N2)O(N^2)O(N2),每个状态扩展时需遍历两个棋子各自的出边,总边数为MMM。最坏情况下每个状态遍历所有边,总复杂度为O(N2⋅M)O(N^2 \cdot M)O(N2⋅M)。由于N≤100N \le 100N≤100,M≤10000M \le 10000M≤10000,最坏约为10810^8108次操作,在时间限制内可行(实际测试通过)。空间复杂度O(N2)O(N^2)O(N2)用于存储距离数组。

正确性说明

BFS\texttt{BFS}BFS按层次扩展状态,第一次到达目标状态时所经过的边数即为最短路径长度。由于移动代价均为111,且转移条件仅依赖于当前状态,满足最优子结构,因此BFS\texttt{BFS}BFS给出的结果必然是最优解。

代码实现

// Game// UVa ID: 767// Verdict: Accepted// Submission Date: 2026-07-04// UVa Run Time: 0.010s//// 版权所有(C)2026,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constintINF=-1;// BFS 返回最小步数,若不可达返回 -1intbfs(intN,intL,intK,intQ,constvector<int>&circleColor,constvector<vector<pair<int,int>>>&adj){vector<vector<int>>dist(N+1,vector<int>(N+1,-1));queue<pair<int,int>>q;dist[L][K]=0;q.push({L,K});while(!q.empty()){autocur=q.front();q.pop();intu=cur.first,v=cur.second;intd=dist[u][v];// 移动第一个棋子 ufor(auto&e:adj[u]){intnxt=e.first,col=e.second;if(col==circleColor[v]&&nxt!=v){if(nxt==Q)returnd+1;if(dist[nxt][v]==-1){dist[nxt][v]=d+1;q.push({nxt,v});}}}// 移动第二个棋子 vfor(auto&e:adj[v]){intnxt=e.first,col=e.second;if(col==circleColor[u]&&nxt!=u){if(nxt==Q)returnd+1;if(dist[u][nxt]==-1){dist[u][nxt]=d+1;q.push({u,nxt});}}}}return-1;}intmain(){intnumDatasets;cin>>numDatasets;boolfirstCase=true;for(intcaseIdx=0;caseIdx<numDatasets;++caseIdx){intN,L,K,Q;cin>>N>>L>>K>>Q;vector<int>circleColor(N+1);for(inti=1;i<=N;++i)cin>>circleColor[i];intM;cin>>M;vector<vector<pair<int,int>>>adj(N+1);for(inti=0;i<M;++i){intA,B,C;cin>>A>>B>>C;adj[A].push_back({B,C});}intans=bfs(N,L,K,Q,circleColor,adj);// 输出,数据集间空行if(!firstCase)cout<<"\n";firstCase=false;if(ans==-1){cout<<"NO\n";}else{cout<<"YES\n"<<ans<<"\n";}}return0;}

总结

本题的关键在于正确建模双棋子状态,利用BFS\texttt{BFS}BFS求最短路径。由于状态数有限,直接枚举所有状态并进行转移是可行的。需要注意的细节包括:

  • 两个棋子不能同时位于同一圆圈,转移时必须检查目标位置是否被另一棋子占据。
  • 颜色比较时使用另一个棋子所在圆圈的颜色,而非当前移动棋子的颜色。
  • 初始三个整数L,K,QL, K, QL,K,Q互不相同,但题目已保证,不必额外校验。

该解法思路清晰,代码简洁,能够通过所有测试数据。若NNN或MMM更大,可能需要考虑更高效的状态压缩或双向BFS\texttt{BFS}BFS,但在本题限制下,标准BFS\texttt{BFS}BFS已足够。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 18:35:33

开源贡献指南:如何将任意音频模型移植到MLX Audio Swift

【免费下载链接】mlx-audio-swift A modular Swift SDK for audio processing with MLX on Apple Silicon 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ml/mlx-audio-swift 点击查看 免费下载 MLX Audio Swift 是一个开源的模块化 Swift 音频 SDK&#xff0c;基于 M…

作者头像 李华
网站建设 2026/10/27 18:33:05

2000-2024年 省级-城乡收入差距泰尔指数数据(xlsx)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/27 18:30:34

nRF52840+DW3000 UWB测距KEIL工程实战指南

简介&#xff1a;本资源是一套面向嵌入式UWB开发者的KEIL MDK工程源码包&#xff0c;专为nRF52833与nRF52840双平台适配DW3000超宽带芯片而设计&#xff0c;填补了官方SDK中缺失KEIL工程及DW3000底层驱动源码的空白&#xff0c;适用于物联网高精度定位、测距、TWR/TDOA等UWB应用…

作者头像 李华
网站建设 2026/10/27 18:27:31

基于Springboot体育馆预约管理系统【附源码+文档】

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/27 18:27:13

Text2SQL全解析:自然语言转SQL的技术演进与落地实践

1. 开篇&#xff1a;不会写SQL的业务同学&#xff0c;不该被数据挡在门外先讲个我每天都在见的场景&#xff1a;运营同学拿着活动复盘的需求来找我&#xff0c;"我想看这个月参与新人礼的用户里&#xff0c;哪些人是通过分享海报进来的&#xff0c;他们之后7天的留存怎么样…

作者头像 李华
网站建设 2026/10/27 18:22:54

Caveman图表库实战:用洞穴人壁画重构数据可视化叙事

机缘巧合&#xff0c;我在整理开源项目收藏夹的时候又翻到了 Caveman 这个库。第一次看到它时&#xff0c;我就被这个另类的数据可视化思路吸引了&#xff1a;一个图表库&#xff0c;不画折线也不画柱状&#xff0c;而是把所有数据映射成一群手持棍棒的洞穴人&#xff0c;数值越…

作者头像 李华