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;
}