【题解】CF1557E Assiut Chess

交互题。

题意:你放置一个皇后的位置,不知道国王的初始位置。国王会向八个方向行动,每次国王先行,双方都必须移动。任何时刻国王都不能移动到皇后的攻击位置。你需要在不管国王怎样移动情况下都保证在有限步数内击败对方。

solution: 比较棘手的是不知道国王的位置。但是真的有必要知道它的位置吗?

比较容易想到的是蛇形走位。假设当前在第 i i i 行 ,那么 1 − i 1-i 1i 行都已经被占领了。我们从第一列开始,从左往右扫一遍,看看会发生什么:

  1. 若国王在第 i + 1 i+1 i+1 列,显然会被逼迫到选择 Down , Down-Left , Right-Down 以躲避攻击。此时可以趁机占领 i + 1 i+1 i+1 列。
  2. 若国王在 ≥ i + 2 \geq i+2 i+2 列,同时没有向下走的话,我们可以占领 i + 1 i+1 i+1 列;如果选择 Up, Up-Left, Up-Right 之一,我们重新从第 1 1 1 列开始从左往右扫,重复上述操作。

根据势能分析,国王到我方的纵向距离单调不增,所以总步数不会超过 7 ∗ 8 + 8 ∗ 8 + 8 = 128 7*8+8*8+8=128 78+88+8=128 步。

一个坑点是,走到当前行的第一个位置是不能算的。

  • 优化1:发现检查一列时可以一次走两个位置,这样常数减少一半。
  • 优化2:我们还可以 启发式搜索 ,维护当前国王可能的位置坐标。如果 i + 1 − j i+1-j i+1j 行全为 0 0 0 的话就直接跳到第 j j j 行,否则找到第一个 ( i + 1 , p ) = 1 (i+1,p)=1 (i+1,p)=1 的点,然后移动到 ( i , p ) (i,p) (i,p) 。具体编码比较复杂,可以用 队列 来实现。这样的话步数大概在 15 15 15 步左右。还有一个细节就是如果对方是 Up, Up-Left, Up-Right 的话,要重复上述操作。

下次做交互题一定要一遍过。。。

#include <bits/stdc++.h> #define INF 0x3f3f3f3f #define PII pair<int,int> #define ll long long using namespace std; int dx[16],dy[16]; void solve() { int x,y=1; for(x=1;x<=8;x++) { int ok(0); cout<<x<<" "<<y<<endl; string op; cin>>op; if(op=="Done") return; y=(y==1)?3:1; while(y<=7) { cout<<x<<" "<<y<<endl; string op; cin>>op; if(op=="Done") return; if(op[0]=='D') { ok=1; break; } if(op[0]=='U') { y=(y==1)?3:1; continue; } //对方没有向上下移动,说明不在 x+1 行 if(y==7) { ok=1; break; } else y+=2; } } } signed main() { // freopen("data.in","r",stdin); for(int i=0;i<7;i++) dx[i]=1,dy[i]=0; dy[7]=-1; for(int i=8;i<15;i++) dx[i]=-1; dy[15]=-1; int T; scanf("%d",&T); while(T--) { solve(); } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530292.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示