YKpages

ロボット分野で勉強したことのまとめ

AtCoder Regular Contest 006 D 今日から始める競プロ日記

はじめに

chokudaiさんの今日の一問を解いてみた。

AtCoder Regular Contest 006 D

結局、他の人の提出コードを参考にしてAC。

D - アルファベット探し

与えられた図の中から A、B、C の図形がそれぞれ何個あるか数える問題。

atcoder.jp

解いた方針

各図形のマスを数える

30分くらい考えていたら、 各図形を形作っている黒マスの数がそれぞれ異なっていることに気づいた。

  • Aは12マス
  • Bは16マス
  • Cは11マス

さらに、 図形を整数倍してもそれぞれのマスの数は判別できそうだった。

  • 図形を2倍にすると、マスの数は2*2=4倍
  • 図形を3倍にすると、マスの数は3*3=9倍
  • 図形を4倍にすると、マスの数は4*4=16倍
  • ......

各図形を整数倍したときのマスの数

Aのマス数 Bのマス数 Cのマス数
1 12 16 11
2 12x2x2=48 16x2x2=64 11x2x2=44
3 12x3x3=108 16x3x3=144 11x3x3=99
4 12x4x4=192 16x4x4=256 11x4x4=176
... ... ... ...

つまり黒マスの数をカウントすれば、 その図形が A なのか、B なのか、C なのかが判別できる。

一つの図形のマスだけを数える方法

まず、黒マスを一つ見つける。

見つけた黒マスの周り8マスの見て、 また黒マスがあればそちらに移動する。

この処理を再帰的に行う。

f:id:kato_robotics:20190824171105p:plain
マス数のカウント1
f:id:kato_robotics:20190824171153p:plain
マス数のカウント2
f:id:kato_robotics:20190824171225p:plain
マス数のカウント3
f:id:kato_robotics:20190824171259p:plain
マス数のカウント4

こんな感じで黒マスを5つカウントできた(カウントの順番は実装方法によるため、図の通りになるかは分からない)。

コード

数えるところまでは実装できたけど、 図形の判別方法でおかしくなってしまった。

WAの原因が分からなかったので、 同じころに提出してACしていたta7uwさんのコードを参考にしたらACした(ありがたい)。

ta7uwさんの提出コード:

atcoder.jp

自分が提出したコード:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef long long ll;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
 
vector<string> field(10010);
int ans[3] = {0};
int cnt = 0;
 
void painting(int i, int j)
{
    for(int x: dx) {
        for(int y: dy) {
            if(field[i+x][j+y] == 'o') {
                cnt++;
                field[i+x][j+y] = '.';
                painting(i+x, j+y);
            }
        }
    }
    return;
}
 
int check(int a)
{
    for(int i = 2; i*i <= a; i++) {
        while(a % (i*i) == 0) a /= (i*i);
    }
    return a;
}
 
int main()
{
    int H, W; cin >> H >> W;
    for(int i = 0; i < H; i++) {
        cin >> field[i];
    }
    for(int i = 1; i < H-1; i++) {
        for(int j = 1; j < W-1; j++) {
            if(field[i][j] == 'o') {
                cnt = 0;
                painting(i, j);
                int a = check(cnt);
                if(a == 3) ans[0]++;
                else if(a == 1) ans[1]++;
                else if(a == 11) ans[2]++;
            }
        }
    }
    cout << ans[0] << " " << ans[1] << " " << ans[2] << endl;
    return 0;
}

おわりに

ふつうに難しかった。

今日から始める競プロ日記のまとめページ

kato-robotics.hatenablog.com