Gromah 最近沉迷于一款叫做 “贪吃蛇大作战” 的游戏。
给定一个 (n imes m) 的地图,其中有些格子是空的,有些格子上有食物。初始时贪吃蛇的头在地图中的某个格子上,且贪吃蛇初始只有一个头,每次 Gromah 会控制贪吃蛇的头朝着上下左右四个方向中的一个方向移动一个单位,如果贪吃蛇的头撞到了墙(即坐标不在 ((1,1) - (n,m)) 范围内),则其立即死亡,否则如果贪吃蛇的头所到达的格子上有一个食物,则贪吃蛇会吃掉这个食物,然后身体立即增加 1 的长度,当然一个食物被吃掉之后就会消失。
具体地,每当进行一次移动,如果没有吃掉一个食物,则贪吃蛇在头部按照给定方向进行移动的同时,身体的每一段也朝着前一段身体的方向进行移动;如果吃掉了一个食物,则只有头部进行移动,原来身体不进行移动,原来的头部位置长出一个单位的身体,即贪吃蛇的身体增加 1 的长度。
特别地,贪吃蛇的头可以和自己的身体重合(起码游戏里是这样子的),保证贪吃蛇的初始位置上不存在食物。
现给定地图,贪吃蛇的头的初始位置,移动序列。如果贪吃蛇中途撞到了墙,则输出GG,否则如果贪吃蛇最后还活着,输出地图的最后状态,具体请见输出格式及样例输出。
这恶题想复杂了卡我好久,别人都用的队列,就我一个玩奇怪转化
队列方法就不说了,光说说我的做法
首先我们考虑移动位置是可以转化成区间加的,所以就可以把操作对x和y的贡献做一个前缀和
然后再考虑一个食物在第i个操作被吃了之后,如果之后不吃东西,它会在头后面一直跟着走,也就是会进行i+1~n这段操作
那么再考虑吃了一个食物后对身子的影响:它们会全都停顿一下,那么应该进行到n操作就只能到n-1了
这样就非常好做了,我们记录这个食物被吃的时候的操作编号i,这个食物是第几个被吃的mov
那么这个点进行的操作就是i+1~n-mov这段,然后用前缀和就能直接算出贡献了
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
const int N = 400;
const int M = 1e5;
using namespace std;
int n,m,len,stx,sty,mov[N + 5][N + 5],cntx[M + 5],cnty[M + 5],cnt,mm[N + 5][N + 5];
char ch[N + 5][N + 5],t[M + 5],ans[N + 5][N + 5];
int main()
{
scanf("%d%d",&n,&m);
for (int i = 1;i <= n;i++)
scanf("%s",ch[i] + 1);
scanf("%s",t + 1);
len = strlen(t + 1);
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
if (ch[i][j] == '@')
{
stx = i;
sty = j;
}
for (int i = 1;i <= len;i++)
{
cntx[i] = cntx[i - 1];
cnty[i] = cnty[i - 1];
if (t[i] == 'W')
cntx[i]--;
if (t[i] == 'A')
cnty[i]--;
if (t[i] == 'S')
cntx[i]++;
if (t[i] == 'D')
cnty[i]++;
}
int x = stx,y = sty;
for (int i = 1;i <= len;i++)
{
if (t[i] == 'W')
x--;
if (t[i] == 'A')
y--;
if (t[i] == 'S')
x++;
if (t[i] == 'D')
y++;
if (x < 1 || x > n || y < 1 || y > m)
{
cout<<"GG"<<endl;
return 0;
}
if (ch[x][y] == 'o')
mm[x][y] = i,mov[x][y] = ++cnt,ch[x][y] = '.';
}
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
ans[i][j] = ch[i][j];
ans[stx][sty] = '.';
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
if (mov[i][j])
ans[i + cntx[len - mov[i][j]] - cntx[mm[i][j]]][j + cnty[len - mov[i][j]] - cnty[mm[i][j]]] = 'X';
ans[x][y] = '@';
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= m;j++)
cout<<ans[i][j];
cout<<endl;
}
return 0;
}