[BOJ 2667]番号のみ
26027 ワード
質問元:[BOJ 2667]番号だけ貼って、https://www.acmicpc.net/problem/2667
👨🏫質問する
👨🏫質問する
図1に示すように、正方形の地図があります.1は家がある場所、0は家がない場所を表します.哲洙はこの地図で団地を定義しようとしたが、それはつながった家の集合であり、団地番号を与えた.ここでつながっているのは、ある家に左右や上下の異なる家があることを意味します.対角線に家がある場合はつながっていません.<【図2】<図1>を単一番号で示す図である.地図を入力してセル数を出力し、各セルの家屋数を昇順に並べてプログラムを作成してください.
入力
1行目は地図サイズN(正方形、横方向と縦方向のサイズが同じ、5≦N≦25)を入力し、次の行は各N個の資料(0または1)を入力する.
しゅつりょく
最初のローの合計出力数.その後、各園区内の家屋の数を昇順に並べ、各行に1つ出力します.
サンプルI/O
入力例
7
0110100
0110101
1110101
0000111
0100000
0111110
0111000
サンプル出力
3
7
8
9
💻コード#コード# import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Stack;
public class DanG {
static int[][] map;
static boolean[][] visited;
static int[] location;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
ArrayList<Integer> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int N = Integer.parseInt(br.readLine());
map = new int[N][N];
visited = new boolean[N][N];
for(int i = 0; i < N; i++){
String line = br.readLine();
for(int j = 0; j < line.length(); j++){
map[i][j] = line.charAt(j) - '0';
}
}
/*
* 지도를 순회하다 방문하지 않은 집이 있을 경우,
* 해당 좌표를 기준으로 search 메서드 호출
*/
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
if(visited[i][j] == false && map[i][j] == 1){
list.add(search(new int[] {i, j}));
}
}
}
// 단지의 크기가 작은 순서부터 출력해야 하므로 오름차순 정렬
Collections.sort(list);
sb.append(list.size() + "\n");
for(int i = 0; i < list.size() - 1; i++){
sb.append(list.get(i) + "\n");
}
sb.append(list.get(list.size() - 1));
System.out.println(sb);
}
// 단지에 있는 집의 수를 반환해주는 메서드
static int search(int[] location){
int[] dy = {-1, 0, 1, 0};
int[] dx = {0, 1, 0, -1};
int y = location[0];
int x = location[1];
Stack<int[]> stack = new Stack<>();
// 단지 내 집의 수를 저장해 줄 변수
int count = 0;
visited[y][x] = true;
stack.push(location);
count++;
while(!stack.isEmpty()){
int[] peek = stack.peek();
boolean flag = false;
// 현재 좌표를 기준으로 상 하 좌 우 확인
for(int i = 0; i < 4; i++){
int ny = peek[0] + dy[i];
int nx = peek[1] + dx[i];
/*
* 상 하 좌 우 검사 시 배열의 범위를 벗어나지 않는지 확인
* 방문한 적이 없는 집인 경우 stack에 push하고, 해당 좌표를 방문 처리
*/
if(isBound(new int[]{ny, nx}) && visited[ny][nx] == false && map[ny][nx] == 1){
stack.push(new int[]{ny, nx});
visited[ny][nx] = true;
flag = true;
count++;
break;
}
}
// 근처에 더 이상 방문할 집이 없을 경우 stack에서 pop
if(!flag){
stack.pop();
}
}
return count;
}
// 상 하 좌 우를 검사 할 때 배열의 길이를 넘는지 확인해주는 함수
static boolean isBound(int[] location){
if((location[0] >= 0 && location[1] >= 0) &&
(location[0] < map.length && location[1] < map[0].length)){
return true;
}
return false;
}
}
💡ポスト
深さ優先探索(DFS)または幅優先探索(BFS)を利用することは解決可能な問題である.
個人的には探索問題をするとき、DFSもBFSも解けるなら、BFSを利用した方が個人的に分かりやすいので、BFSの方が好きですが、DFSはまだ慣れていないのでDFSで解いてみます.😁
もう少し探索問題を作って、DFSに慣れた時にbacktracking問題に挑戦しましょう!
Reference
この問題について([BOJ 2667]番号のみ), 我々は、より多くの情報をここで見つけました
https://velog.io/@jaeung5169/BOJ-2667-단지번호붙이기
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Stack;
public class DanG {
static int[][] map;
static boolean[][] visited;
static int[] location;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
ArrayList<Integer> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int N = Integer.parseInt(br.readLine());
map = new int[N][N];
visited = new boolean[N][N];
for(int i = 0; i < N; i++){
String line = br.readLine();
for(int j = 0; j < line.length(); j++){
map[i][j] = line.charAt(j) - '0';
}
}
/*
* 지도를 순회하다 방문하지 않은 집이 있을 경우,
* 해당 좌표를 기준으로 search 메서드 호출
*/
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
if(visited[i][j] == false && map[i][j] == 1){
list.add(search(new int[] {i, j}));
}
}
}
// 단지의 크기가 작은 순서부터 출력해야 하므로 오름차순 정렬
Collections.sort(list);
sb.append(list.size() + "\n");
for(int i = 0; i < list.size() - 1; i++){
sb.append(list.get(i) + "\n");
}
sb.append(list.get(list.size() - 1));
System.out.println(sb);
}
// 단지에 있는 집의 수를 반환해주는 메서드
static int search(int[] location){
int[] dy = {-1, 0, 1, 0};
int[] dx = {0, 1, 0, -1};
int y = location[0];
int x = location[1];
Stack<int[]> stack = new Stack<>();
// 단지 내 집의 수를 저장해 줄 변수
int count = 0;
visited[y][x] = true;
stack.push(location);
count++;
while(!stack.isEmpty()){
int[] peek = stack.peek();
boolean flag = false;
// 현재 좌표를 기준으로 상 하 좌 우 확인
for(int i = 0; i < 4; i++){
int ny = peek[0] + dy[i];
int nx = peek[1] + dx[i];
/*
* 상 하 좌 우 검사 시 배열의 범위를 벗어나지 않는지 확인
* 방문한 적이 없는 집인 경우 stack에 push하고, 해당 좌표를 방문 처리
*/
if(isBound(new int[]{ny, nx}) && visited[ny][nx] == false && map[ny][nx] == 1){
stack.push(new int[]{ny, nx});
visited[ny][nx] = true;
flag = true;
count++;
break;
}
}
// 근처에 더 이상 방문할 집이 없을 경우 stack에서 pop
if(!flag){
stack.pop();
}
}
return count;
}
// 상 하 좌 우를 검사 할 때 배열의 길이를 넘는지 확인해주는 함수
static boolean isBound(int[] location){
if((location[0] >= 0 && location[1] >= 0) &&
(location[0] < map.length && location[1] < map[0].length)){
return true;
}
return false;
}
}
💡ポスト
深さ優先探索(DFS)または幅優先探索(BFS)を利用することは解決可能な問題である.
個人的には探索問題をするとき、DFSもBFSも解けるなら、BFSを利用した方が個人的に分かりやすいので、BFSの方が好きですが、DFSはまだ慣れていないのでDFSで解いてみます.😁
もう少し探索問題を作って、DFSに慣れた時にbacktracking問題に挑戦しましょう!
Reference
この問題について([BOJ 2667]番号のみ), 我々は、より多くの情報をここで見つけました
https://velog.io/@jaeung5169/BOJ-2667-단지번호붙이기
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Reference
この問題について([BOJ 2667]番号のみ), 我々は、より多くの情報をここで見つけました https://velog.io/@jaeung5169/BOJ-2667-단지번호붙이기テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol