백준

백준(14890번) - 경사로(Java) (구현)

kjih1104 2024. 3. 12. 20:39

 동서남북 4곳 모두에서 반대쪽으로 지나간다고 되어 있으니, 간단하게 (북 -> 남 / 서 -> 동) 이 2가지 경로만 반대쪽으로 넘어갈 수 있는지 검사해 봤다. 각각의 경우 안에서도 또 2가지 경우로 나눠지는데

 

북(서) -> 남(동)으로 움직이는 도중

 1. 앞칸이 지금 칸보다 한 칸 낮은 경우

 2. 앞칸이 지금 칸보다 한 칸 높은 경우

 

총 4가지 경우의 수를 고려해서 작성해 봤다.

import java.util.*;
import java.io.*;


public class Main
{
	static int n, l, ans;
	static int[][] map;
	public static void main (String[] args) throws IOException
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		n = Integer.parseInt(st.nextToken());
		l = Integer.parseInt(st.nextToken());
		map = new int[n][n];
		
		for(int i = 0 ; i < n ; i++)
		{
			st = new StringTokenizer(br.readLine());
			for(int j = 0 ; j < n ; j++)
			{
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		for(int i = 0 ; i < n ; i++)
		{
			if(down(i)) ans++;
			
			if(right(i)) ans++;
		}
		
		System.out.println(ans);
	}
	public static boolean down(int c)
	{
		for(int i = 0 ; i < n ; i++)
		{
			if(i-1 >= 0 && map[i-1][c] - map[i][c] == 1)
			{
				int cnt = 1;
				
				for(int j = 1 ; j < l ; j++)
				{
					if(i+j >= n || map[i][c] != map[i+j][c]) return false;
					
					cnt++;
				}
				
				if(cnt < l) return false;
			}
			else if(i+1 < n && map[i+1][c] - map[i][c] == 1)
			{
				int cnt = 1;
				
				for(int j = 1 ; j < l ; j++)
				{
					if(i-j < 0 || map[i][c] != map[i-j][c]) return false;
					
					cnt++;
				}
				
				if(cnt < l) return false;
			}
		}
		
		return true;
	}
	public static boolean right(int r)
	{
		for(int i = 0 ; i < n ; i++)
		{
			if(i-1 >= 0 && map[r][i-1] - map[r][i] == 1)
			{
				int cnt = 1;
				
				for(int j = 1 ; j < l ; j++)
				{
					if(i+j >= n || map[r][i] != map[r][i+j]) return false;
					
					cnt++;
				}
				
				if(cnt < l) return false;
			}
			else if(i+1 < n && map[r][i+1] - map[r][i] == 1)
			{
				int cnt = 1;
				
				for(int j = 1 ; j < l ; j++)
				{
					if(i-j < 0 || map[r][i] != map[r][i-j]) return false;
					
					cnt++;
				}
				
				if(cnt < l) return false;
			}
		}
		
		return true;
	}
}

테스트 케이스조차 통과하지 못했는데 이런 코드로 작동할 경우 경사로를 놓은 칸에 중복으로 경사로를 넣지 말아야 한다는 문제 조건을 위반할 위험이 있기 때문이다. 이 부분을 보완하고 깔끔하게 다듬은 것이 정답 코드이다.

<문제>

https://www.acmicpc.net/problem/14890

 

14890번: 경사로

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

www.acmicpc.net


<소스코드>

import java.util.*;
import java.io.*;


public class Main
{
	static int n, l, ans;
	static int[][] map;
	public static void main (String[] args) throws IOException
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		n = Integer.parseInt(st.nextToken());
		l = Integer.parseInt(st.nextToken());
		map = new int[n][n];
		
		for(int i = 0 ; i < n ; i++)
		{
			st = new StringTokenizer(br.readLine());
			for(int j = 0 ; j < n ; j++)
			{
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		for(int i = 0 ; i < n ; i++)
		{
			if(down(i)) ans++;
			
			if(right(i)) ans++;
		}
		
		System.out.println(ans);
	}
	public static boolean down(int c)
	{
		boolean[] visit = new boolean[n];    //경사로를 넣었는가를 의미
		
		for(int i = 0 ; i < n-1 ; i++)
		{
			if(Math.abs(map[i][c] - map[i+1][c]) > 1) return false;
			
			if(map[i+1][c] - map[i][c] == -1)	//밑이 1단 낮은 경우
			{
				for(int j = i+1 ; j <= i+l ; j++)
				{
					if(j >= n || map[i+1][c] != map[j][c] || visit[j]) return false;
					
					visit[j] = true;
				}
			}
			
			if(map[i+1][c] - map[i][c] == 1)	//밑이 1단 높은 경우
			{
				for(int j = i ; j > i-l ; j--)
				{
					if(j < 0 || map[i][c] != map[j][c] || visit[j]) return false;
					
					visit[j] = true;
				}
			}
		}
		
		return true;
	}
	public static boolean right(int r)
	{
		boolean[] visit = new boolean[n];    //경사로를 넣었는가를 의미
		
		for(int i = 0 ; i < n-1 ; i++)
		{
			if(Math.abs(map[r][i] - map[r][i+1]) > 1) return false;
			
			if(map[r][i+1] - map[r][i] == -1)	//밑이 1단 낮은 경우
			{
				for(int j = i+1 ; j <= i+l ; j++)
				{
					if(j >= n || map[r][i+1] != map[r][j] || visit[j]) return false;
					
					visit[j] = true;
				}
			}
			
			if(map[r][i+1] - map[r][i] == 1)	//밑이 1단 높은 경우
			{
				for(int j = i ; j > i-l ; j--)
				{
					if(j < 0 || map[r][i] != map[r][j] || visit[j]) return false;
					
					visit[j] = true;
				}
			}
		}
		
		return true;
	}
}