CF1503B 题解
t162
2021-04-04 12:22:36
## 题目大意
这是一道交互题。
你需要和交互库玩一个游戏。交互库每次给出一个属于 $[1,3]$ 的整数,你需要在一个 $n\times n$ 的网格图中任意一个格子上填写一个属于 $[1,3]$ 且和交互库给出的整数不同的整数。
如果任意时刻网格图中相邻两个格子(有公共边)上的数相同,你就输了,否则你就赢了。
你需要赢得这个游戏。
## 换位思考
如果你是交互库,你打算怎么玩?
其实容易想到,如果网格图中出现任意一个空的格子,其四周中的格子里中有不同的数,那么你一直给出没有出现过的那个数,到最后你就赢了。
举个例子,如果一个空的格子,其上方格子中填了 $1$,右方格子填了 $2$,那么你只要一直给出 $3$,对手就一直没法填这个空格子。
想到这里就差不多了。
## 解题
我们为了避免上面那种情况,可以考虑交错着填,填到最后达到这种状态:
![](https://cdn.luogu.com.cn/upload/image_hosting/00zba8xm.png)
或这种状态:
![](https://cdn.luogu.com.cn/upload/image_hosting/1g64jb8t.png)
其中同一张图中黄色格子中填的数字是一样的,白色格子可填可不填,但填的数字不能和黄色格子中数字一样。
这样,剩余的空格子就可以很轻松填完了(因为不论交互库给出什么整数,剩余的任意一个空格子总有至少一种数字可填)。
具体实现的时候,如下图。为了达到上面那两种状态之一,我们可以规定红色格子填一个固定值,黄色格子填另一种固定值,如果交互库给出的数等于红色格子中的值,那么就填黄色格子,否则就填红色格子。最终,总有一种颜色的格子被先填满,也就是到达上面两种状态之一。
![](https://cdn.luogu.com.cn/upload/image_hosting/vk53pdvt.png)
## 代码实现
代码中,我是斜着填的,当然这样写太麻烦了,容易出错,可以横着填,竖着填。
```cpp
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<limits>
namespace StandardLibrary {
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::fixed;
using std::flush;
using std::setprecision;
using std::setw;
using std::numeric_limits;
}
using namespace StandardLibrary;
#include<algorithm>
#include<bitset>
#include<complex>
#include<deque>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<utility>
#include<vector>
namespace STL {
using std::bitset;
using std::complex;
using std::deque;
using std::greater;
using std::less;
using std::map;
using std::pair;
using std::priority_queue;
using std::queue;
using std::set;
using std::stack;
using std::string;
using std::vector;
using std::make_pair;
using std::sort;
}
using namespace STL;
#define rep(var, start, end) for(int var = (start), var##_end = (end); var <= var##_end; var++)
#define rrep(var, start, end) for(int var = (start), var##_end = (end); var >= var##_end; var--)
namespace IO {
template <typename T>
inline T read(T& dest) {
int c = getchar(); T f = 1; dest = 0;
while (c < 48 || c > 57) f *= (c == 45 ? -1 : 1), c = getchar();
while (c >= 48 && c <= 57) dest = (dest << 3) + (dest << 1) + (c ^ 48), c = getchar();
return dest *= f;
}
template <typename T, typename... args>
inline void read(T& dest, args&... dests) { read(dest), read(dests...); }
template <typename T>
inline T read() {
int c = getchar(); T f = 1, dest = 0;
while (c < 48 || c > 57) f *= (c == 45 ? -1 : 1), c = getchar();
while (c >= 48 && c <= 57) dest = (dest << 3) + (dest << 1) + (c ^ 48), c = getchar();
return dest * f;
}
template <typename T>
inline void put(T val) {
T tmp = 0, l = 0; if (val < 0) putchar('-'), val = -val;
while (val) tmp = tmp * 10 + (val % 10), l++, val /= 10;
if (l == 0) putchar('0');
else {
while (l) putchar((tmp % 10) + 48), l--, tmp /= 10;
while (l) putchar('0'), l--;
}
}
template <>
inline void put<char*>(char* val) { rep(i, 0, ((int)strlen(val)) - 1) putchar(val[i]); }
template <>
inline void put<const char*>(const char* val) {
rep(i, 0, ((int)strlen(val)) - 1) putchar(val[i]);
}
template <>
inline void put<string>(string val) { put(val.c_str()); }
template <typename T, typename... args>
inline void put(T val, args&... values) { put(val), putchar(' '), put(values...); }
template <typename T>
inline void write(T val) {
put(val), putchar(' ');
}
template <typename T, typename... args>
inline void write(T val, args&... values) { write(val), write(values...); }
inline void writeln() { puts(""); }
template <typename T>
inline void writeln(T val) { put(val), writeln(); }
template <typename T, typename... args>
inline void writeln(T val, args&... values) { put(val), putchar(' '), writeln(values...); }
}
using namespace IO;
namespace Tools {
template <typename T, typename... args>
inline void log(T val) { cerr<<val<<endl; }
template <typename T, typename... args>
inline void log(T val, args... lists) { cerr<<val<<' '; log(lists...); }
}
using namespace Tools;
//=======正文开始=======
int a[201][201];
int n, k, oi = 1, oj = 1, ei = 2, ej = 1, flag = 1, li = 1, lj = 1;
void _put(int b, int i, int j) { a[i][j] = b, writeln(b,i,j), fflush(stdout); } //填充函数
int main() {
read(n);
for (int i = 1; i <= n * n; i++) {
int d; read(d);
if (k == 0) { //确定两种格子颜色
if (d == 1) {
_put(2, 1, 1), k = 2, oi++, oj++;
} else _put(1, 1, 1), k = 1, oi++, oj++;
} else if (flag) { //未达到两种状态
if (d == k) {
_put(3 - k, ei, ej);
ei++, ej++;
if (ei > n) ei -= n, ej -= (n & 1);
if (ej > n) ej -= n, ei -= (n & 1);
if (a[ei][ej]) {
if (ei == n || ei == n - 1) flag = 0;
else ei += 2;
}
} else {
_put(k, oi, oj);
oi++, oj++;
if (oi == oj && oi > n) oi -= n, oj -= n;
if (oi > n) oi -= n, oj += (n & 1);
if (oj > n) oj -= n, oi += (n & 1);
if (a[oi][oj]) {
if (oi == n || oi == n - 1) flag = 0;
else oi += 2;
}
}
} else { //达到两种状态之一
int f = 0;
for (; li <= n; li++) {
if (lj == n + 1) lj = 1;
for (; lj <= n; lj++) {
if (a[li][lj]) continue;
if ((li >= lj && (li - lj) % 2 == 1) || ((li < lj) && (lj - li) % 2 == 1)) {
if (3 - k == d) _put(3, li, lj);
else _put(3 - k, li, lj);
} else {
if (d == k) _put(3, li, lj);
else _put(k, li, lj);
}
f = 1; break;
}
if (f) break;
}
}
}
}
```