方阵贪吃蛇的必胜策略
包含本题的交互题单。
https://qoj.ac/contest/3588/problem/17759
一道上次深圳 ICPC 的交互,感觉是签到,因为我同学去打了但是我没去,我太菜了,欢迎且膜拜全国各地来深圳比赛的选手。
就是传统的贪吃蛇,不能碰墙,每一次移动之后头不可以和身体某一部分重合(特别地,如果长度为 \(2\),调换蛇的方向并不会违反这个规定)。身体增长是体现在:造成进食的那一步本身,蛇的尾部不会空出来。
给你初始坐标和每一次吃完苹果后下一个苹果出现的位置(只会出现在空位)。让你返回贪吃蛇的走法,你需要使得你可以最终使贪吃蛇填满屏幕(交互体现在这个东西是在线的,你必须要吃完目前的苹果才会给你下一个苹果的坐标,并且你目前蛇的形态会影响评测机下一次给你的坐标)。
强化问题:我们想构造一个回路,使得其经过所有点刚好一次。这样让蛇头沿着这条回路一直走就好了。
然后就是黑白染色分析,得出以下结论。
- 考虑如果有至少一条边是偶数,可以直接构造如下图的方案。

- 如果两条边都是奇数呢?尝试构造。

然后根据苹果的位置,每次可以走橙线/红线。
因为最后一次吃之前只剩一格,一定是在橙红线中没有被走的那个上出现,然后发现这时拐进去吃刚好会填满整张图,不会碰到蛇本身,于是问题解决。
代码(对于奇数情况,我后面找到了一个更好写的构造方法,于是和上述不一样,所以主要看一下实现方式):
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 57;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
//D, R, U, L
map<char, int> mp;
map<char, char> tr;
int vis[N][N], n, m;
char a[N][N];
void solve(){
int f = 0;
cin >> n >> m;
mp['D'] = 0, mp['R'] = 1, mp['U'] = 2, mp['L'] = 3;
tr['D'] = 'D', tr['R'] = 'R', tr['U'] = 'U', tr['L'] = 'L';
for(int i = 1; i <= max(n, m); i ++)
for(int j = 1; j <= max(n, m); j ++) vis[i][j] = 1;
if((n & 1) && (m & 1)){
for(int i = 1; i < m; i ++) a[1][i] = 'R';
a[1][m] = 'D';
for(int i = m; i > 2; i --){
if(i & 1){
for(int j = 2; j < n; j ++) a[j][i] = 'D';
a[n][i] = 'L';
}
else{
for(int j = n; j > 2; j --) a[j][i] = 'U';
a[2][i] = 'L';
}
}
for(int i = n; i > 1; i --){
if(i & 1) a[i][1] = 'U', a[i][2] = 'L';
else a[i][1] = 'R', a[i][2] = 'U';
}
vis[1][1] = 0;
}
else{
if(!(m & 1)){
swap(n, m), f = 1;
swap(tr['R'], tr['D']);
swap(tr['U'], tr['L']);
}
for(int i = n; i >= 2; i --) a[i][1] = 'U';
a[1][1] = 'R';
for(int i = 1; i <= n; i += 2){
for(int j = 2; j < m; j ++) a[i][j] = 'R';
a[i][m] = 'D';
for(int j = m; j > 2; j --) a[i + 1][j] = 'L';
a[i + 1][2] = 'D';
}
a[n][2] = 'L';
}
int x, y; cin >> x >> y;
if(f) swap(x, y);
int cnt = n * m - 1;
while(cnt --){
int r, c; cin >> r >> c;
if(f) swap(r, c);
if(!vis[r][c]){
a[2][1] = 'U' + 'R' - a[2][1];
vis[1][1] = 1 - vis[1][1], vis[2][2] = 1 - vis[2][2];
}
while(x != r || y != c){
int dir = mp[a[x][y]];
cout << tr[a[x][y]];
x += dx[dir], y += dy[dir];
}
cout << endl;
}
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0);
int t; cin >> t;
while(t --) solve();
return 0;
}

浙公网安备 33010602011771号