題目敘述
每筆資料第一行有三個正整數M、N、K,接下來要收一個M*N的二維字元陣列,之後的一行有K個整數,代表要往哪裡走。題目的字元結構是採蜂巢形,下面有圖片做參考。0 是往右上; 1 是往右邊; 2 是往右下; 3 是往左下; 4 是往左邊; 5 是往左上。
要求每步移動的方向,請輸出經過的路徑每格的代表字母,以及經過字元的種類數 (大小寫相異),若經過時碰到牆壁該行動會停在原地,屆時要輸出目前該位置的字元。
範例輸入 #1
2 4 5
TyuI
ABaB
0 1 2 3 0
範例輸出 #1
Tyaau
4
範例輸入 #2
4 6 11
rMmnis
LRveEX
ZexDoc
HAdbHA
0 1 5 1 1 0 3 0 0 1 0
範例輸出 #2
ZeLRvmvmmnn
7
解題思路
本題比較複雜的地方是因為題目的結構是蜂巢狀,但是收資料的時候是採正方形的方式。但是可以理解為:右上的時候x和y值的變化為 (0, -1)、右邊的時候為 (1, 0)、右下的時候為 (1, 1)、左下的時候為 (0, 1)、左邊的時候為 (-1, 0)、左上的時候為 (-1, -1)。如果不理解的話可以拿範例一的資料用畫的方式畫畫看就會大概知道這個概念。需要注意的是每次行走時都需要判斷這樣子走會不會超出陣列的邊界。輸出次數的部分可以使用Map來存已經出現過的字元。
解題程式碼如下 (僅供參考):
#include <iostream>
#include <map>
#include <vector>
using namespace std;
pair<int, int>rtn (int a, int b)
{
pair<int, int>tmp;
tmp.first = a;
tmp.second = b;
return tmp;
}
int main() {
int M, N, K;
cin >> M >> N >> K;
cin.ignore();
vector<string>v;
for (int i = 0; i<M; i++)
{
string tmp;
getline(cin, tmp);
v.push_back(tmp);
}
int x = 0, y = M-1;
map<int, pair<int, int>>MAP;
MAP[0] = rtn(0, -1);
MAP[1] = rtn(1, 0);
MAP[2] = rtn(1, 1);
MAP[3] = rtn(0, 1);
MAP[4] = rtn(-1, 0);
MAP[5] = rtn(-1, -1);
map<char, int>appear;
int ans = 0;
for (int i = 0; i<K; i++)
{
int tmp;
cin >> tmp;
int xx = x + MAP[tmp].first, yy = y + MAP[tmp].second;
//cout << xx << " " << yy;
if (xx >= 0 && xx < N && yy >= 0 && yy < M)
{
x = xx;
y = yy;
char ch = v[y][x];
if (isalpha(ch))
{
cout << ch;
if (appear[ch] == 0) ans++;
appear[ch]++;
}
}
else
{
char ch = v[y][x];
if (isalpha(ch))
{
cout << ch;
if (appear[ch] == 0) ans++;
appear[ch]++;
}
}
}
cout << "\n" << ans << "\n";
}
留言
張貼留言