1 条题解
-
0
题目分析
这是一个交互式问题,需要在网格中找到宝箱的位置。关键约束是:
- 宝箱会阻挡机器人移动
- 每次查询后机器人回到起点
- 需要在最少次查询内确定宝箱位置
算法思路
核心思想
使用两次查询策略:
- 第一次查询:水平移动探测,快速确定宝箱是否在右侧路径上
- 第二次查询:复杂蛇形路径,精确定位宝箱位置
关键观察
- 如果宝箱不在机器人移动路径上,机器人会到达预期位置
- 如果宝箱在路径上,机器人会被阻挡,最终位置会暴露宝箱信息
- 通过精心设计路径,可以在两次查询内唯一确定宝箱位置
代码详解
交互函数
pair<int,int> ask(string s){ cout<<"? "<<s<<'\n'; fflush(stdout); int x,y; cin>>x>>y; return make_pair(x,y); }第一次查询:水平探测
string s = ""; for(int i = 0; i < m; i++) s += ">"; // 构造纯右移指令 auto v = ask(s); // 如果机器人没有到达最右端,说明宝箱在水平路径上 if(v.S != m - 1){ cout<<"! "<<v.F<<" "<<v.S + 1<<'\n'; return 0; }逻辑:
- 如果宝箱在
(r, c)且c < m-1,机器人会在宝箱前一格停止 - 最终位置直接给出宝箱的列坐标:
v.S + 1 - 行坐标就是机器人停止的行:
v.F
第二次查询:蛇形路径探测
s = "v"; // 先向下移动一格 for(int i = 1; i < n; i++){ for(int j = 0; j < m; j++) s += ">"; // 向右移动到底 s += "^>v"; // 向上、右、下(形成Z字形) for(int j = 0; j < m; j++) s += "<"; // 向左移动到底 s += "v"; // 向下移动 } for(int i = 0; i < m; i++) s += ">"; // 最后向右移动到底 v = ask(s);位置推断逻辑
if(v.S == m - 1){ // 到达最右列,说明宝箱在第一列 if(v.F == n - 1) v.F = 0; // 边界处理 cout<<"! "<<v.F + 1<<" "<<0<<'\n'; } else { // 未到达最右列,根据最终位置推断宝箱位置 cout<<"! "<<v.F<<" "<<v.S + 1<<'\n'; }算法原理
路径设计分析
第二次查询的路径设计:
- 起始:
v- 向下移动,避开(0,0)起点 - 循环结构:对于每行
i(从1到n-1):>>>...- 向右移动到底^>v- 向上、右、下,形成Z字转折<<<...- 向左移动到底v- 向下移动
- 结束:
>>>...- 最后向右移动到底
为什么这样能确定所有位置?
- 宝箱在内部:会被蛇形路径探测到,机器人停止位置指示宝箱坐标
- 宝箱在第一列:只有这种情况机器人能到达最右端
- 宝箱在最后位置:特殊边界条件处理
复杂度分析
查询次数
- 最优情况:1次查询(宝箱在水平路径上)
- 最坏情况:2次查询
- 满足得分公式要求: 可得100分
- 1
信息
- ID
- 5590
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者