cf1205c(div1)

35 篇文章 0 订阅
2 篇文章 0 订阅

第一道交互题

题意:

  • 生成一个n*n的矩阵(n是奇数), 每个矩阵上的元素是0或1, 你的交互程序要在小于 n 2 n^2 n2个询问中猜出这个矩阵
  • 定义询问: x1, y1, x2, y2, 分别代表起点和终点, 而且终点必须在起点的右下方, 而且两者不能不能相邻, 题目会返回在起点和终点的任意一条路径中是否有一条路径是回文串, (路径的方向只能向右或者向下)
  • 矩阵的左上角是1, 矩阵的右下角是0;

数据范围: n ≤ 50 n \leq 50 n50

>> face <<

前置技能: 无

Tutorial: 不难发现所有横纵坐标之和为偶数的所有坐标都可以被一次询问确定(针对已经确定的x,y, 询问x+2,y或者x+1, y+1, 或者x, y+2, 由于路径的长的是3, 所以是否对称决定始末是否相同), 且如果假设a[1][2] = 0, 那么所有的横纵坐标之和是奇数的也可以被确定(同上), 现在的问题就是验证a[1][2]的假设是否正确, 如果不正确, 应该把所有的横纵坐标之和为奇数的所有值反转

验证过程

#include<bits/stdc++.h>
using namespace std;
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (int i = (a); i >= (b); --i)
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rof(i, a, b) for (int i = (a); i > (b); --i)
#define oo 0x3f3f3f3f
#define ll long long
#define db double
#define eps 1e-8
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl;
#define met(a, b) memset(a, b, sizeof(a))
#define all(x) x.begin(), x.end()
#define pii pair<int, int>
const int maxn = 100;
int a[maxn][maxn], n;
bool vis[maxn][maxn], f[maxn][maxn];
int quary(int x1, int y1, int x2, int y2)
{
	printf("? %d %d %d %d\n", x1, y1, x2, y2);
	fflush(stdout);
	int ret;
	scanf("%d", &ret);
	return ret;
}
vector<pii> q;
void dfs(int x1, int y1, int x2, int y2, int cur)
{
	if (vis[x2][y2])
		return;
	if (x2 == n && y2 == n)
		return;
	if (x2 > n || y2 > n)
		return;
	if (x1 != 0 && y1 != 0)
		a[x2][y2] = (quary(x1, y1, x2, y2) == 1 ? cur : !cur);
	vis[x2][y2] = 1;
	dfs(x2, y2, x2 + 2, y2, a[x2][y2]);
	dfs(x2, y2, x2 + 1, y2 + 1, a[x2][y2]);
	dfs(x2, y2, x2, y2 + 2, a[x2][y2]);
}
bool check(int x1, int y1, int x2, int y2) {
	int res = quary(x1, y1, x2, y2);
	return (res ? !a[x1][y1] == a[x2][y2] : a[x1][y1] == a[x2][y2]);
}
int cnt;
bool find0(int x, int y)
{
	if (x > n || y > n)
		return 0;
	bool& t = f[x][y];
	if (t || vis[x][y])
		return t;
	vis[x][y] = 1;
	if (x + 3 <= n && y <= n)
	{
		t |= ((a[x][y] ^ a[x + 1][y] ^ a[x + 2][y] ^ a[x + 3][y]) == 0);
		if (t) {
			q.push_back(make_pair(x, y)), q.push_back(make_pair(x + 3, y));
			return t;
		}
	}
	if (x + 2 <= n && y + 1 <= n)
	{
		t |= ((a[x][y] ^ a[x + 1][y] ^ a[x + 2][y] ^ a[x + 2][y + 1]) == 0);
		t |= ((a[x][y] ^ a[x][y + 1] ^ a[x + 1][y + 1] ^ a[x + 2][y + 1]) == 0);
		if (t) {
			q.push_back(make_pair(x, y)), q.push_back(make_pair(x + 2, y + 1));
			return t;
		}
	}
	if (x + 1 <= n && y + 2 <= n)
	{
		t |= ((a[x][y] ^ a[x + 1][y] ^ a[x + 1][y + 1] ^ a[x + 1][y + 2]) == 0);
		t |= ((a[x][y] ^ a[x][y + 1] ^ a[x][y + 2] ^ a[x + 1][y + 2]) == 0);
		if (t) {
			q.push_back(make_pair(x, y)), q.push_back(make_pair(x + 1, y + 2));
			return t;
		}
	}
	if (x <= n && y + 3 <= n)
	{
		t |= ((a[x][y] ^ a[x][y + 1] ^ a[x][y + 2] ^ a[x][y + 3]) == 0);
		if (t) {
			q.push_back(make_pair(x, y)), q.push_back(make_pair(x, y + 3));
			return t;
		}
	}
	return t || find0(x + 1, y) || find0(x + 1, y + 1) || find0(x, y + 1);
}

void flip()
{
	_rep(i, 1, n)
	{
		for (int j = (i & 1 ? 2 : 1); j <= n; j += 2)
		{
			a[i][j] = !a[i][j];
		}
	}
}

signed main()
{
	cin >> n;
	//met(a, 0), met(vis, 0);
	a[1][1] = 1;
	dfs(0, 0, 1, 1, 1);
	dfs(0, 0, 1, 2, 0);
	for (int i = 2; i <= n; i += 2)
		a[i][1] = (quary(i, 1, i + 1, 2) == 1 ? a[i + 1][2] : !a[i + 1][2]);

	met(vis, 0);
	find0(1, 1);
	if (check(q[0].first, q[0].second, q[1].first, q[1].second))
		flip();
	printf("!\n"),
		fflush(stdout);
	_rep(i, 1, n) {
		_rep(j, 1, n) {
			printf("%d", a[i][j]), fflush(stdout);
		}
		printf("\n"), fflush(stdout);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值