ABC107B解けた

投稿者: | 2018年9月11日

最近何もしてなくて何してるんだろうというぐらいに何もしてません。気がついたら解いてない問題が溜まってたので、とりあえずA問題とB問題を解いてました。いつもはC問題解けたらメモ代わりに書いてますが、今回はABC107のB問題です。2次元配列を縦と横に探索していくので、後で使えるかなあと思ってます。いやこれぐらいはいつでも使えるようにはしたいですが・・・。

[blogcard url=”https://beta.atcoder.jp/contests/abc107/tasks/abc107_b”]

まずは問題を読む

感覚としては、選択した部分を削除して左詰め/上詰めするような、エクセルの行/列削除みたいな感じです。消す部分は、全て’.’で成っている行/列。エクセルだったら、何もデータの入ってない行や列を削除する感じかなあ?とか思ってました。

とりあえずやることとしては、「一列または一行が全て’.’の行や列を削除し、その部分を詰める」コードを書くことになります。

詰める?

消す部分を探してその空いた部分を詰めて表示するというコードを書かなくてはなりません。しかし、配列の空いた部分を詰めるって大分めんどくさそう・・・。なので、あとで消す部分がわかるように、違う文字で置き換えておきます。そして出力するときに、その文字を出力しないようにすれば、出力されたデータは詰められた状態になります。

消す部分を探す

探し方は愚直に、一列または一行全部見て、全部’.’だったら違う文字に置き換え、です。早くなってるのか謎ですが、なんとなく、「一行または一列全て’.’なら、最低限、最初と最後は’.’じゃないと全部探す気にならないよねえ」とか思って、「行または列の最初と最後が’.’だった場合のみ、その行または列を見る」という書き方にしてます。

このとき、全て’.’だったら違う文字で置き換えるわけですが、条件文を「全て’.’だったら」というふうにしているとミスりました。私は行を見てから縦を見たわけですが、次のような場合、列を見るときに失敗します。

##.#
….
##.#
.#.#

まず行を見ていくと、2行目が全て違う文字で置き換えられます。行を見おわったら次は列を見ていきますが、3列目は全て違う文字に置き換えられるはずですが、2行3列目の文字は行を見ているときに違う文字で置き換えられていて、’.’ではないので、条件に一致せず、プログラムは「この行は全て’.’じゃなかった」と言って文字を置き換えません。このせいで20分使いました。

なので、後に行う処理の条件文は「’.’もしくは置き換えられた文字」にします。

綺麗に出力したい

一番時間かかったのが出力でした。ただ単純に「置き換えた文字は出力しない」ってやればいいやと思ったら、これ改行しなくちゃいけないんですね。その改行にすごく苦労してました。

普通に2次元配列の中身を表示すればいいんですが、そのままだと次のような感じになります。

出力
###

###
.##

2行目でも改行されて変な空白が出ます。これを消したい。なので、もうめんどくさくなってたので、bool型のflagという変数を作って、毎行文字を出力したらflag=1にして改行、そうでない場合は改行しないという、なんだかなあという感じになりました。

以上のことをコードにしたら、次のようになりました。

#include <iostream>
using namespace std;
int main(int argc, char const *argv[]) {
int h,w;
cin>>h>>w;
char a[h][w];
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
cin>>a[i][j];
}
}
//横方向に探索
for(int i=0;i<h;i++){
if(a[i][0]=='.'&&a[i][w-1]=='.'){
for(int j=1;j<w-1;j++){
if(a[i][j]=='#') break;
if(j==w-2){
for(int k=0;k<w;k++){
a[i][k]='*';
}
}
}
}
}
//縦方向に探索
for(int i=0;i<w;i++){
if(a[0][i]!='#'&&a[h-1][i]!='#'){
for(int j=1;j<h-1;j++){
if(a[j][i]=='#') break;
if(j==h-2){
for(int k=0;k<h;k++){
a[k][i]='*';
}
}
}
}
}
// //debug:一回全部表示させてみる
// for(int i=0;i<h;i++){
// for(int j=0;j<w;j++){
// cout<<a[i][j];
// }
// cout<<endl;
// }
//0以外を出力
bool flag=0;
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
if(a[i][j]!='*'){
cout<<a[i][j];
flag=1;
}
}
if(flag){
cout<<endl;
flag=0;
}
}
return 0;
}

コメントを残す

This site uses Akismet to reduce spam. Learn how your comment data is processed.