比較常,需比較多時間和記憶體,但是對初學這友善的寫法:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int m,n,k;
cin>>m>>n>>k;
string w[m]; //m個字
for (int i=0; i<m; i++){
cin>>w[i];
}
int comm[k]; //k個指令
for (int i=0; i<k; i++){
cin>>comm[i];
}
string ss;
ss.resize(k,'0'); //先resize,讓答案長度為k的string先有東西填接下來才能百裡面char代替
int cy=m-1; //c是current,現在的意思,這是現在的y
int cx=0;
int dx[6]={0,1,1,0,-1,-1}; //x方向移動對照上圖做調整(調整解釋放下方)
int dy[6]={-1,0,1,1,0,-1}; //y方向移動對照上圖做調整(調整解釋放下方)
for (int i=0; i<k; i++){
int fx=cx+dx[comm[i]]; //f是future,未來(下一步)
int fy=cy+dy[comm[i]]; //未來y=現在y+方向y的第k[i](輸入指令指定)個
if (fx<0 || fy<0 || fx>=n || fy>=m){ //檢查是否超出邊界,如果超出邊界則:
fx-=dx[comm[i]]; //fx減掉方向x的第k[i](輸入指令指定)個回到原本cx
fy-=dy[comm[i]]; //fy減掉方向y的第k[i](輸入指令指定)個回到原本cy
}
cy=fy; //重新更新,確認不管有沒有超出邊界皆更新成剛剛判斷的格子
cx=fx;
ss[i]=w[cy][cx]; //把ss(答案)的第i個char(預設為0)改成現在踩上的格子之char
}
int a[26]={0}; //小寫字母
int A[26]={0}; //大寫字母(題目說大小寫算不同種)
for (int i=0; i<ss.size(); i++){
if (islower(ss[i])){ //如果ss[的第i字母是小寫則true
a[ss[i]-'a']++; //a陣列第ss[i]-'a'格加一(ASCII中,所有英文字母都有對應整數值,ss[i]-'a'會得到一個整數,e.g. ss[i]='a'則ss[i]-'a'=0,我在這設有26格從0-25,0是a一直到25是z)表示以正常方式數的第"ss[i]-'a'+1"個英文字母知小寫數量加一
}
else{
A[ss[i]-'A']++; //同a陣列,但是以'A'為基準,因為是大寫(ASCII是先'a', 'b'..., 'z'再'A', 'B'... 'Z')
}
}
int count=0; //不同種字母數
for (int i=0; i<26; i++){ //兩陣列皆0-25
if (a[i]!=0){ //只要對照正常abcd歌中的第"a[i]+1"(從1開始算的話)字母不是0(不管數量,只要有存在就好)則多一種字母(count++)
count++;
}
if (A[i]!=0){ //只要對照正常ABCD歌中的第"A[i]+1"(從1開始算的話)字母不是0(不管數量,只要有存在就好)則多一種字母(count++)
count++;
}
}
cout<<ss<<endl; //輸出字串+換行
cout<<count; //輸出字母種類數量
}
方向調整解釋:
透過觀察,發現如果不改原本字的index,可以用方向調整
e.g.
TyuI ABaB
可以發現,T原本在測資輸入/紀錄中是正上方,但是在圖中和實際操作為右上,因此全部又上皆往左平移成為正上方,w[1][0]=A時,正上方成為w[0][0]=T,可以對應途中的右上方。以此邏輯挪動與平移改方向即可。