一道模拟题,我用到了维克托的二维数组与前缀和的方法,其实前缀和可以省略,题目给的输出有点奇怪,当时没想出来,在结束后捣鼓了一下写了出来。
#include<bits/stdc++.h>
using namespace std;
const int N =1010;
int s[N];
int main()
{
int n,m,x,y;
int cnt=0;
cin >> n >> m >> x >> y;
int dc[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
vector<int>room[n+2][n+2];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
room[i][j].push_back(0);
}
}
string s1;
cin >> s1;
int num=0;
//模拟走地图
for(auto c:s1){
num++;
if(c=='N'){
room[x][y].push_back(num);
x+=0;
y+=1;
}
if(c=='S'){
room[x][y].push_back(num);
x+=0;
y+=-1;
}
if(c=='W'){
room[x][y].push_back(num);
x+=-1;
y+=0;
}
if(c=='E'){
room[x][y].push_back(num);
x+=1;
y+=0;
}
}
for(int i=1;i<=num;i++) s[i]+=s[i-1]+i;
for(int j=n;j>=1;j--){
for(int i=1;i<=n;i++){
//if(room[i][j].empty()) printf("%d ",s[num]);
// else{
for(auto z=room[i][j].begin();z!=room[i][j].end();z++){
if(*z!=0) cnt+=s[*z-*(z-1)-1];
}
auto z=room[i][j].end()-1;
//cout << *z;
cnt+=s[num-(*z)];
printf("%d ",cnt);
cnt=0;
// }
}
printf("\n");
}
return 0;
}
有些多余的组件与无用的注释,可以提醒我当时我测试时候犯的错和思路,这里简单回顾一下,
1.首先我选择使用了一个表示方向的数组,这个是我在矩阵模拟题里面用过的,但是矩阵模拟题是有特定的规律而这个是给多少走多少,可以不用数组简洁代码。
2.在模拟走路的时候,我一开始使用了从0开始的数组,导致我的x和y与我想要的结果不相符。所以应该在维克托初始化的时候开大一点然后在模拟走路的时候从11开始。
3.答案的输出是以左下角为(1,1),纵深为y轴,左右为x轴的输出格式,这就需要从(1,5)开始遍历,外层是y轴,内层是x轴。
4.使用迭代器的时候,要记住begin和end是左闭右开区间,end是取不到的,所以最后一个值应该是end-1,且迭代器是以地址的方式存储,所以要解引用。这个题的主要思路是一个格子存下来被走的时候是第几步,例如第一步被走,那么就应该用前缀和加cnt+=s【1-0】,后续再加上到达终点的步数s【num-最后一步】,但是一个格子可能被踩过多次,所以使用了一个计算中间相差步数的方法来计算该有的累加步数,但是这样又牵扯到了上一步,然后上一步可能数组越界,因此采用了全体赋0且当是第0步的时候不计算相当于略过数组第一项从第二项开始计算前一步略去了数组越界的可能,我认为这是这道题的难点,就是怎么样用程序来表达累加的步数。
希望下次遇到类似的模拟题能更顺利得根据这次的经验写出来。