这是一个互动的问题。李明和李华在玩游戏。李华有一个大小为n × m的棋盘,用(r, c) (1 S r S n, 1≤c≤m)表示上的单元格上面的第r行左边的第c列。李明在棋盘上放了一个王,李华需要猜它的位置。李华最多只能问李明3个问题。在每个问题中,他可以选择一个单元格,并询问移动该单元格所需的最小步骤国王到选定的牢房。每个问题都是独立的,这意味着国王实际上不会动。国王可以从(z,y)移动到(æ',y')当且仅当max{lz-x'l, ly-y'l} = 1(如下图所示)。
国王的位置是在互动之前选定的。假设你是李华,请解决这个问题。交互第一行包含测试用例的数量t(1≤t≤103)。每个测试用例的第一行包含两个整数n, m (1 < n, m < 10°)——棋盘的大小,然后交互开始。要问问题,请打印“?”r c”(不带引号,1 <r n,1 < c m),然后输入标准输入的响应- king移动到所选单元格所需的最小步长。如果你的程序问了一个无效的问题,或者已经没有问题了,交互器将立即终止,你的程序将得到一个错误答案。要给出最终答案,请打印“!”C”(不带引号,(r, C)是国王的初始坐标)。请注意,给出这个答案不计入3个问题的限制。问完一个问题后,不要忘记输出行尾并刷新输出。否则,您将得到闲置限制超过。要做到这一点,请使用:fflush(stdout) 或 cout.flush() inC++;Java中的System.out.flush ();Pascal中的flush(输出);stdout。Python中的flush ();有关其他语言,请参阅文档。黑客要破解,请使用以下格式。第一行应该包含一个整数t (1 < t < 103)。每个测试用例的第一行和唯一一行应该包含四个整数n, m, r,c (1 <r < n < 10°,1≤c≤m < 10°)。
Example
input
Copy
2 3 4 1 2 5 3 3 1 2
output
Copy
? 2 3 ? 2 4 ! 2 2 ? 2 2 ? 5 2 ? 5 3 ! 5 1
题解:
我们可以首先取左上,与右下两个顶点,得到这两个点到目标点的距离a,b,由于是国王,所以八个方向均可走,所有点到这我们取两个点的的距离为a,b的,可以构成两个正方形
如果两个正方形有交边,那么目标点肯定在,那条边上,那我们就已经确定了x轴或y轴的坐标
再询问一下目标点到(x,1),或(1,y)的距离即可
当然还有两个正方形相交的情况,通过观察,我们发现,这样的目标点,只可能在左下,或右上这些部分
所以我们判断一下到底是在左下还是右上即可,限制一下左下的情况,如果目标点到,我们的所求的点距离为0,肯定是在左下,否则反转180度在右上
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
//#define int long long
int ask(int x,int y)
{
cout <<"? " << x <<" "<<y <<"\n";
int ans;
cin >> ans;
return ans;
}
void solve()
{
int n,m;
cin >> n >> m;
int a = ask(1,1);
int b = ask(n,m);
int x,y;
if(a +b == n - 1)
{
x = 1 + a;
y = 1 + ask(x,1);
}
else if(a + b == m - 1)
{
y = 1 + a;
x = 1 + ask(1,y);
}
else
{
if(a + 1 <= n&&m - b >= 1&&ask(a + 1,m - b) == 0)
{
x = a + 1;
y = m - b;
}
else
{
y = a + 1;
x = n - b;
}
}
cout << "! " << x <<" "<<y <<"\n";
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}