백준공부/java
[백준] 17070번 파이프 옮기기 1 (gold 5
gomduri43
2024. 1. 2. 17:40
import java.io.*;
import java.util.*;
class Point{
int x;
int y;
int v;
public Point(int x, int y, int v){
this.x=x;
this.y=y;
this.v=v;
}
}
public class Main{
static int n;
static int[][] map;
public static void main(String[] args )throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
n=Integer.valueOf(br.readLine());
map=new int[n+1][n+1];
for(int i=1; i<=n; i++){
st=new StringTokenizer(br.readLine());
for(int j=1; j<=n; j++){
map[i][j]=Integer.valueOf(st.nextToken());
}
}
//가로 0 //세로 1 //대각선 2
Queue<Point> que=new LinkedList<>();
que.offer(new Point(2,1,0));
int answer=0;
if(map[n][n]!=1) {
while (!que.isEmpty()) {
Point temp = que.poll();
if (temp.x == n && temp.y == n) {
answer++;
} else if (temp.v == 0) {
if (cross(temp.x, temp.y)) {
que.offer(new Point(temp.x + 1, temp.y, 0));
}
if (dakak(temp.x, temp.y)) {
que.offer(new Point(temp.x + 1, temp.y + 1, 2));
}
} else if (temp.v == 1) {
if (dakak(temp.x, temp.y)) {
que.offer(new Point(temp.x + 1, temp.y + 1, 2));
}
if (height(temp.x, temp.y)) {
que.offer(new Point(temp.x, temp.y + 1, 1));
}
} else {
if (cross(temp.x, temp.y)) {
que.offer(new Point(temp.x + 1, temp.y, 0));
}
if (dakak(temp.x, temp.y)) {
que.offer(new Point(temp.x + 1, temp.y + 1, 2));
}
if (height(temp.x, temp.y)) {
que.offer(new Point(temp.x, temp.y + 1, 1));
}
}
}
}
bw.write(answer+"");
bw.flush();
}
public static boolean cross(int x, int y){
if(x+1>n || map[y][x+1]==1){
return false;
}
else {
return true;
}
}
public static boolean height(int x, int y){
if(y+1>n || map[y+1][x]==1){
return false;
}
else {
return true;
}
}
public static boolean dakak(int x, int y){
if(x+1>n || y+1>n || map[y][x+1]==1 || map[y+1][x]==1 || map[y+1][x+1]==1){
return false;
}
else {
return true;
}
}
}
// bfs를 이용한 풀이 하지만, 80%부근의 테스트케이스가 n이 16인 케이스. 이때 que에 들어가는
// 노드의 수가 계속해서 3혹은 2의 지수로 증가하기 때문에 엄청난 갯수가 들어가서 시간초과를 발생한다.
// 따라서 bfs로는 16인 경우, 마지막이 벽이라 그 예외만 처리하면 정답으로 통과가 되지만 사실상 완전한
// 풀이는 아니다. dfs로 길을 하나하나 찾아가야 노드에 많은 수가 몰리는걸 막을 수 있기 때문이다.
// (visit으로 방문처리도 안되고 갔던 지점을 다른 곳에서 다시 도달하는 경우들도 많ㅇ므.
// 따라서 dp를 이용한 풀이를 해야 적절하다.
// cpp에서는 dfs도 통과. 하지만 추가시간이 없어서 java나 python을 이용해서는 통과가 안됨.
import java.io.*;
import java.util.*;
public class Main{
static int n;
static int[][] map;
static int[][][] dp;
public static void main(String[] args )throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
n=Integer.valueOf(br.readLine());
map=new int[n+1][n+1];
for(int i=1; i<=n; i++){
st=new StringTokenizer(br.readLine());
for(int j=1; j<=n; j++){
map[i][j]=Integer.valueOf(st.nextToken());
}
}
dp=new int[n+1][n+1][3];
dp[1][2][0]=1;
//가로 0 //세로 1 //대각선 2
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(map[i][j]==1){
continue;
}
dp[i][j][0]+=dp[i][j-1][0];
dp[i][j][0]+=dp[i][j-1][2];
dp[i][j][1]+=dp[i-1][j][1];
dp[i][j][1]+=dp[i-1][j][2];
if(dakak(j,i)) {
dp[i][j][2] += dp[i - 1][j - 1][2];
dp[i][j][2] += dp[i - 1][j - 1][0];
dp[i][j][2] += dp[i - 1][j - 1][1];
}
}
}
bw.write(dp[n][n][0]+dp[n][n][1]+dp[n][n][2]+"");
bw.flush();
}
public static boolean dakak(int x, int y){
if(map[y][x-1]==1 || map[y-1][x]==1 || map[y][x]==1){
return false;
}
else{
return true;
}
}
}
// dp를 이용한 풀이
// 여기서 세가지 경우 즉 가로 , 세로, 대각선의 케이스가 있으므로 각각의 다른 배열방에 값 저장하고.
// 이를 이용해서 풀이를 해나가면된다.