yokobuttonの不定期で競技プログラミングをするブログ

不定期で解けた競技プログラミングコンテストの問題を載せています。

AtCoder Beginner Contest 241(Sponsored by Panasonic)C - Connect 6

問題の要約
 N行N列のマス目があり、それぞれマスは白または黒で塗られている。
 マス目の状態はN個の文字列Siで表され、Siのj文字目が#であることはマス目の上からi行目、左からj列目のマスが黒く塗られていることを、.であることは白く塗られていることをさす。
 このマス目のうち高々2つの白く塗られているマスを選び、黒く塗ることができる。
 マス目の中に、黒く塗られているマスが縦、横、ななめのいずれかの向きに6つ以上連続するようにできるか判定しろ。
制約
 6<=N<=1000
 |Si|=N
入力
 N
 S1
 S2
 ...
 SN
考え方
 1、左上から順に右下まで探索することを考える。
  1000*1000=10^6なので高速に黒が6つ以上連続するかどうか調べる方法があれば大丈夫そう。
 2、左上から順に調べるので、調べる方向は右横、下縦、右ななめ下、左ななめ下の4方向だけでよい。
 3、黒が6つ以上連続するかを調べるのではなく、6つマスを調べて白が2以下であるかを調べる。
 4、調べる際に、N行N列の枠から出ないように気をつける。
実際のプログラム
#include<iostream>
#include<vector>

using namespace std;

int N;
vector<string> S;

bool check_1(int i, int j){
  int white = 0;
  bool flag = false;
  for(int k = 0; k < 6; k++){
    if(N <= j+k){
      return flag;
    }
    if(S[i][j+k] == '.'){
      white++;
    }
  }
  if(white <= 2){
    flag = true;
  }
  return flag;
}

bool check_2(int i, int j){
  int white = 0;
  bool flag = false;
  for(int k = 0; k < 6; k++){
    if(N <= i+k){
      return flag;
    }
    if(S[i+k][j] == '.'){
      white++;
    }
  }
  if(white <= 2){
    flag = true;
  }
  return flag;
}

bool check_3(int i, int j){
  int white = 0;
  bool flag = false;
  for(int k = 0; k < 6; k++){
    if(N <= i+k || N <= j+k){
      return flag;
    }
    if(S[i+k][j+k] == '.'){
      white++;
    }
  }
  if(white <= 2){
    flag = true;
  }
  return flag;
}

bool check_4(int i, int j){
  int white = 0;
  bool flag = false;
  for(int k = 0; k < 6; k++){
    if(N <= i+k || j-k < 0){
      return flag;
    }
    if(S[i+k][j-k] == '.'){
      white++;
    }
  }
  if(white <= 2){
    flag = true;
  }
  return flag;
}

int main(){
  cin >> N;
  S.resize(N);
  for(int i = 0; i < N; i++){
    cin >> S[i];
  }
  
  bool flag = false;
  for(int i = 0; i < N; i++){
    for(int j = 0; j < N; j++){
      if(check_1(i,j) || check_2(i,j) || check_3(i,j) || check_4(i,j)){
        flag = true;
      }     
    }
  }
  
  if(flag){
    cout << "Yes" << endl;
  }else{
    cout << "No" << endl;
  }
  
  return 0;
}