見出し画像

ABC197 B 解答

B - Visibility(96)

問題文

縦 H 行、横 W 列のマス目があり、いくつかのマスには障害物が置かれています。上から i 番目、左から j 番目のマスをマス(i, j)と表すことにします。
H 個の文字列 S_1, S_2, S_3, … , S_H が与えられます。S_i の j 文字目はマス (i, j)の状態を表し、'#' なら障害物が置かれていることを、'.' なら障害物が置かれていないことを表します。
このマス目上のあるマスからあるマスが見えるとは、2つのマスが同じ行または列にあり、2つのマスの間 (2つのマス自身を含む) に障害物が 
1 つも置かれていないことを意味します。
このマス目上のマスであって、マス目 (X, Y)から見えるもの (マス 
(X, Y)自身を含む) の数を求めてください。

制約

1 ≤ H ≤ 100
1 ≤ W ≤100
1 ≤ X ≤ H
1 ≤ Y ≤ W
S_i は '.' および '#' のみからなる
長さ W の文字列
マス(X, Y)に障害物は置かれていない

考察

本問題の制約は

 H  100
 W 100

と小さいので、見えるマス目を一つずつ数え上げていくことで答えを得ることが可能です。

現在あなたは、X、Yにいます。ですので、そのマスから上下左右にマスを動かして行き

" . "が出現するマス

を数え上げましょう。そのために

”#”が出現
配列の外になる(0
XH-1, 0WW-1 からはみ出す)

となったら、カウントをやめましょう。

あとは、あなたが現在いるマスを忘れないようにしましょう。

実装

#include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define reps(i,s,n) for(int i=s;i<n;++i)
using namespace std;
using ll = long long;
using P = pair<intint>;

int main()
{
   int h,w,x,y;
   cin >> h>>w>>x>>y;
   --x,--y;
   vector<string> s(h);
   rep(i,h) cin >> s[i];

   int ans = 1;
   for(int i = x+1; i<=h-1 && s[i][y] != '#';++i) ++ans;
   for(int i = x-10<=i && s[i][y] != '#';--i) ++ans;
   for(int i = y+1; i<=w-1 && s[x][i] != '#';++i) ++ans;
   for(int i = y-10<=i && s[x][i] != '#';--i) ++ans;
   cout << ans << endl;
   return 0;
}

あとがき

for文をうまいこと使って書いていいます。for文は

for(変数の宣言;継続条件;変数の変更)

という構造をしています。実装のfor文をwhile文に直してみると

int i = x+1;
while(i<=h-1 && s[i][y]!='#')
{
    ++ans;
    ++i;
}

となります。私もいつもは

for(int i = 0;繰り返し回数;++i)

ぐらいの認識で使ってましたが、こんなに便利に使えるのですね。

また、文字列を受け取る際には1次元の配列が便利です。A問題でもありましたが、文字列は s[i] のようにすることで、配列の要素にアクセスするのと同様に i 番目の文字を取得できます。s[i][j]は、配列の i 番目のインデックス(i 行目の文字列 )s[i]の j 番目の文字を指し示すことになります。結果として、2次元配列のように操作が可能です。これもとっても便利ですね。

この記事が気に入ったらサポートをしてみませんか?