4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다.

  1. 한 쌍의 괄호로만 이루어진 ‘()’와 ‘[]’는 올바른 괄호열이다.
  2. 만일 X가 올바른 괄호열이면 ‘(X)’이나 ‘[X]’도 모두 올바른 괄호열이 된다.
  3. X와 Y 모두 올바른 괄호열이라면 이들을 결합한 XY도 올바른 괄호열이 된다.

예를 들어 ‘(()[[]])’나 ‘(())[][]’ 는 올바른 괄호열이지만 ‘([)]’ 나 ‘(()()[]’ 은 모두 올바른 괄호열이 아니다. 우리는 어떤 올바른 괄호열 X에 대하여 그 괄호열의 값(괄호값)을 아래와 같이 정의하고 값(X)로 표시한다.

  1. ‘()’ 인 괄호열의 값은 2이다.
  2. ‘[]’ 인 괄호열의 값은 3이다.
  3. ‘(X)’ 의 괄호값은 2×값(X) 으로 계산된다.
  4. ‘[X]’ 의 괄호값은 3×값(X) 으로 계산된다.
  5. 올바른 괄호열 X와 Y가 결합된 XY의 괄호값은 값(XY)= 값(X)+값(Y) 로 계산된다.

예를 들어 ‘(()[[]])([])’ 의 괄호값을 구해보자. ‘()[[]]’ 의 괄호값이 2 + 3×3=11 이므로 ‘(()[[]])’의 괄호값은 2×11=22 이다. 그리고 ‘([])’의 값은 2×3=6 이므로 전체 괄호열의 값은 22 + 6 = 28 이다.

여러분이 풀어야 할 문제는 주어진 괄호열을 읽고 그 괄호값을 앞에서 정의한대로 계산하여 출력하는 것이다.

입력

첫째 줄에 괄호열을 나타내는 문자열(스트링)이 주어진다. 단 그 길이는 1 이상, 30 이하이다.

출력

첫째 줄에 그 괄호열의 값을 나타내는 정수를 출력한다. 만일 입력이 올바르지 못한 괄호열이면 반드시 0을 출력해야 한다.

예제 입력 1

(()[[]])([])

예제 출력 1

28

예제 입력 2

[][]((])

예제 출력 2

0

더보기

Solution

#include<stdio.h>
#include<string.h>

int main(void)
{
	char str[31]={'\0', };
	int correct[30], current=0, calculate[15]={0, };

	scanf("%s", str);
	for(int i=0;i<strlen(str);i++)
		switch(str[i])
		{
			case '(':
				correct[current++]=0;
				break;
			case '[':
				correct[current++]=1;
				break;
			case ')':
				if(current<=0)
				{
					printf("0\n");
					return 0;
				}
				if(correct[--current]!=0)
				{
					printf("0\n");
					return 0;
				}
				break;
			case ']':
				if(current<=0)
				{
					printf("0\n");
					return 0;
				}
				if(correct[--current]!=1)
				{
					printf("0\n");
					return 0;
				}
				break;
			default:
				printf("0\n");
				return 0;
		}
	if(current!=0)
	{
		printf("0\n");
		return 0;
	}

	for(int i=0;i<strlen(str);i++)
		switch(str[i])
		{
			case '(':
			case '[':
				current++;
				break;
			case ')':
				calculate[current-1]+=2*(calculate[current]==0?1:calculate[current]);
				calculate[current--]=0;
				break;
			case ']':
				calculate[current-1]+=3*(calculate[current]==0?1:calculate[current]);
				calculate[current--]=0;
				break;
		}

	printf("%d\n", calculate[0]);
	return 0;
}
더보기

Solution

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		
		String str=br.readLine();
		int[] correct=new int[30];
		int current=0;
		
		for(int i=0;i<str.length();i++)
			switch(str.charAt(i)) {
			case '(':
				correct[current++]=0;
				break;
			case '[':
				correct[current++]=1;
				break;
			case ')':
				if(current<=0) {
					System.out.println(0);
					return;
				}
				if(correct[--current]!=0) {
					System.out.println(0);
					return;
				}
				break;
			case ']':
				if(current<=0) {
					System.out.println(0);
					return;
				}
				if(correct[--current]!=1) {
					System.out.println(0);
					return;
				}
				break;
			default:
				System.out.println(0);
				return;
			}
		
		if(current!=0) {
			System.out.println(0);
			return;
		}

		int[] calculate=new int[15];
		
		for(int i=0;i<str.length();i++)
			switch(str.charAt(i)) {
			case '(':
			case '[':
				current++;
				break;
			case ')':
				calculate[current-1]+=2*(calculate[current]==0?1:calculate[current]);
				calculate[current--]=0;
				break;
			case ']':
				calculate[current-1]+=3*(calculate[current]==0?1:calculate[current]);
				calculate[current--]=0;
				break;
			}
		
		System.out.println(calculate[0]);
	}	
}

 

728x90

N줄에 0 이상 9 이하의 숫자가 세 개씩 적혀 있다. 내려가기 게임을 하고 있는데, 이 게임은 첫 줄에서 시작해서 마지막 줄에서 끝나게 되는 놀이이다.

먼저 처음에 적혀 있는 세 개의 숫자 중에서 하나를 골라서 시작하게 된다. 그리고 다음 줄로 내려가는데, 다음 줄로 내려갈 때에는 다음과 같은 제약 조건이 있다. 바로 아래의 수로 넘어가거나, 아니면 바로 아래의 수와 붙어 있는 수로만 이동할 수 있다는 것이다. 이 제약 조건을 그림으로 나타내어 보면 다음과 같다.

별표는 현재 위치이고, 그 아랫 줄의 파란 동그라미는 원룡이가 다음 줄로 내려갈 수 있는 위치이며, 빨간 가위표는 원룡이가 내려갈 수 없는 위치가 된다. 숫자표가 주어져 있을 때, 얻을 수 있는 최대 점수, 최소 점수를 구하는 프로그램을 작성하시오. 점수는 원룡이가 위치한 곳의 수의 합이다.

입력

첫째 줄에 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 숫자가 세 개씩 주어진다. 숫자는 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 중의 하나가 된다.

출력

첫째 줄에 얻을 수 있는 최대 점수와 최소 점수를 띄어서 출력한다.

예제 입력 1

3
1 2 3
4 5 6
4 9 0

예제 출력 1

18 6

예제 입력 2

3
0 0 0
0 0 0
0 0 0

예제 출력 2

0 0

더보기

Solution

#include<stdio.h>
#include<stdlib.h>

int max3(int x,int y,int z)
{
	if(x>=y&&x>=z)
		return x;
	else if(y>=x&&y>=z)
		return y;
	else
		return z;
}

int min3(int x,int y,int z)
{
	if(x<=y&&x<=z)
		return x;
	else if(y<=x&&y<=z)
		return y;
	else
		return z;
}

int main(void)
{
	int N, score[2][3], max[2][3], min[2][3];

	scanf("%d", &N);

	for(int i=0;i<N;i++)
	{
		for(int j=0;j<3;j++)
			scanf("%d", &score[i%2][j]);
		if(i==0)
		{
			for(int j=0;j<3;j++)
				max[i][j]=min[i][j]=score[i][j];
			continue;
		}

		max[i%2][0]=score[i%2][0]+(max[(i-1)%2][0]>max[(i-1)%2][1]?max[(i-1)%2][0]:max[(i-1)%2][1]);
		max[i%2][1]=score[i%2][1]+max3(max[(i-1)%2][0],max[(i-1)%2][1],max[(i-1)%2][2]);
		max[i%2][2]=score[i%2][2]+(max[(i-1)%2][1]>max[(i-1)%2][2]?max[(i-1)%2][1]:max[(i-1)%2][2]);

		min[i%2][0]=score[i%2][0]+(min[(i-1)%2][0]<min[(i-1)%2][1]?min[(i-1)%2][0]:min[(i-1)%2][1]);
		min[i%2][1]=score[i%2][1]+min3(min[(i-1)%2][0],min[(i-1)%2][1],min[(i-1)%2][2]);
		min[i%2][2]=score[i%2][2]+(min[(i-1)%2][1]<min[(i-1)%2][2]?min[(i-1)%2][1]:min[(i-1)%2][2]);
	}

	printf("%d %d\n", max3(max[(N-1)%2][0],max[(N-1)%2][1],max[(N-1)%2][2]), min3(min[(N-1)%2][0], min[(N-1)%2][1], min[(N-1)%2][2]));

	return 0;
}
728x90

세준이는 학교에서 집으로 가려고 한다. 도시의 크기는 무한대이고, 도시의 세로 도로는 모든 정수 x좌표마다 있고, 가로 도로는 모든 정수 y좌표마다 있다. 세준이는 현재 (0, 0)에 있다. 그리고 (X, Y)에 위치한 집으로 가려고 한다. 세준이가 걸을 수 있는 방법은 두가지 인데, 하나는 도로를 따라서 가로나 세로로 한 블록 움직여서 이번 사거리에서 저 사거리로 움직이는 방법이고, 블록을 대각선으로 가로지르는 방법이 있다.

세준이가 집으로 가는데 걸리는 최소시간을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 집의 위치 X Y와 걸어서 한 블록 가는데 걸리는 시간 W와 대각선으로 한 블록을 가로지르는 시간 S가 주어진다. X와 Y는 1,000,000,000보다 작거나 같은 음이 아닌 정수이고, W와 S는 10,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 세준이가 집에가는데 걸리는 최소시간을 출력한다.

예제 입력 1

4 2 3 10

예제 출력 1

18

예제 입력 2

4 2 3 5

예제 출력 2

16

예제 입력 3

2 0 12 10

예제 출력 3

20

예제 입력 4

25 18 7 11

예제 출력 4

247

예제 입력 5

24 16 12 10

예제 출력 5

240

예제 입력 6

10000000 50000000 800 901

예제 출력 6

41010000000

예제 입력 7

135 122 43 29

예제 출력 7

3929

더보기

Solution

#include<stdio.h>

int main(void)
{
	long X, Y, W, S;

	scanf("%ld%ld%ld%ld", &X, &Y, &W, &S);
	if(2*W<S)
	{
		printf("%ld\n", W*(X+Y));
		return 0;
	}

	if(X>Y)
	{
		X+=Y;
		Y=X-Y;
		X-=Y;
	}

	if(W>S)
		printf("%ld\n", (X+Y)%2==0?S*Y:S*(Y-1)+W);
	else
		printf("%ld\n", S*X+W*(Y-X));

	return 0;
}
728x90

강산이는 심각한 게임 중독자이기 때문에 날씨에 상관없이 매일 PC방을 간다.

최근에 폭우로 인해 일부 지역이 침수되어 침수된 지역으로는 이동할 수 없게 되었다. 하지만 강산이는 출석 이벤트를 위해 하루도 빠짐없이 PC방을 가야 한다.

강산이는 PC방까지 상, 하, 좌, 우 방향으로만 이동하며, 한 번 이동할 때의 거리는 1이다. 또한, 강산이는 게임을 빨리하러 가야 하기 때문에 집에서 PC방까지 최단경로로 움직인다.

강산이의 집의 좌표 (H, H)와 PC방의 좌표 (N, N)이 주어지고 좌표평면 위 (x, y)에서 y > x인 곳은 침수되었다고 할 때, 강산이가 침수된 지역을 피해서 PC방까지 갈 수 있는 경로의 개수를 구하라.

단, PC방의 좌표가 집의 좌표 같은 경우 경로는 1가지라고 한다.

입력

첫째 줄에 집과 PC방의 좌표 (H, H), (N, N) 을 나타내는 두 정수 H, N (0 ≤ H, N ≤ 30) 이 차례로 주어진다.

출력

집에서 PC방까지 갈 수 있는 경로의 개수를 출력한다.

예제 입력 1

8 4

예제 출력 1

14

예제 입력 2

0 3

예제 출력 2

5

더보기

Solution

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
	int H, N;
	long **board=NULL;

	scanf("%d%d", &H, &N);

	if(H==N)
	{
		printf("1\n");
		return 0;
	}
	if(H>N)
	{
		H+=N;
		N=H-N;
		H-=N;
	}
	N-=H;
	H=0;

	board=(long **)malloc((N+2)*sizeof(long *));
	for(int n=0;n<N+2;n++)
		board[n]=(long *)calloc(N+2,sizeof(long));

	for(int i=1;i<N+2;i++)
	{
		board[0][i]=1;
		for(int j=1;j<=i;j++)
			board[i][j]=board[i-1][j]+board[i][j-1];
	}

	printf("%ld\n", board[N+1][N+1]);
	for(int n=0;n<N+2;n++)
		free(board[n]);
	free(board);
	return 0;
}
728x90

1부터 N까지의 수를 이어서 쓰면 다음과 같이 새로운 하나의 수를 얻을 수 있다.

1234567891011121314151617181920212223...

이렇게 만들어진 새로운 수는 몇 자리 수일까? 이 수의 자릿수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N(1 ≤ N ≤ 100,000,000)이 주어진다.

출력

첫째 줄에 새로운 수의 자릿수를 출력한다.

예제 입력 1

5

예제 출력 1

5

예제 입력 2

15

예제 출력 2

21

예제 입력 3

120

예제 출력 3

252

더보기

Solution

#include<stdio.h>

int main(void)
{
	int N, count=0, table[9]={1,10,100,1000,10000,100000,1000000,10000000,100000000};

	scanf("%d", &N);

	for(int n=1;n<=N;n++)
		for(int i=8;i>=0;i--)
			if(n>=table[i])
			{
				count+=i+1;
				break;
			}

	printf("%d\n", count);
	return 0;
}
728x90

자연수 N, M이 주어졌을 때, 1부터 N×M까지 출력 형식대로 출력해보자.

입력

첫째 줄에 공백 한 칸으로 구분한 N, M이 주어진다. 두 수는 1,000보다 작거나 같은 자연수이다.

출력

총 N개의 줄을 출력해야 한다. 각 줄에는 M개의 정수를 공백 한 칸으로 구분해 출력해야 한다. 1번 줄에는 1부터 M까지, 2번 줄에는 M+1부터 2×M까지, ..., N번 줄에는 (N-1)×M+1부터 N×M까지 출력해야 한다.

모든 줄의 시작과 끝에 공백이 있으면 안되고, 모든 줄은 줄바꿈(\n)으로 끝나야 한다.

예제 입력 1

3 4

예제 출력 1

1 2 3 4
5 6 7 8
9 10 11 12

더보기

Solution

#include<stdio.h>

int main(void)
{
	int N, M, count=1;

	scanf("%d%d", &N, &M);

	for(int n=0;n<N;n++)
	{
		for(int m=0;m<M;m++)
		{
			printf("%d", count++);
			if(m<M-1)
				printf(" ");
		}
		printf("\n");
	}

	return 0;
}
728x90

N개의 정수로 이루어진 수열이 있을 때, 크기가 양수인 부분수열 중에서 그 수열의 원소를 다 더한 값이 S가 되는 경우의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 20, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.

출력

첫째 줄에 합이 S가 되는 부분수열의 개수를 출력한다.

예제 입력 1

5 0
-7 -3 -2 5 8

예제 출력 1

1

더보기

Solution

#include<stdio.h>
#include<stdlib.h>

int backtrack(int *arr,int current,int N,int S,int sum,int count)
{
	if(current==N)
		return sum==S&&count>0;
	return backtrack(arr,current+1,N,S,sum+arr[current],count+1)+backtrack(arr,current+1,N,S,sum,count);
}

int main(void)
{
	int N, *arr=NULL, S;

	scanf("%d%d", &N, &S);
	arr=(int *)malloc(N*sizeof(int));

	for(int i=0;i<N;i++)
		scanf("%d", &arr[i]);

	printf("%d\n", backtrack(arr,0,N,S,0,0));
	free(arr);
	return 0;
}
728x90

한가롭게 방학에 놀고 있던 도현이는 갑자기 재밌는 자료구조를 생각해냈다. 그 자료구조의 이름은 queuestack이다.

queuestack의 구조는 다음과 같다. 1번, 2번, ... , 번의 자료구조(queue 혹은 stack)가 나열되어있으며, 각각의 자료구조에는 한 개의 원소가 들어있다.

queuestack의 작동은 다음과 같다.

  • 을 입력받는다.
  • 번 자료구조에 삽입한 뒤 번 자료구조에서 원소를 pop한다. 그때 pop된 원소를 이라 한다.
  • 번 자료구조에 삽입한 뒤 번 자료구조에서 원소를 pop한다. 그때 pop된 원소를 이라 한다.
  • ...
  • 번 자료구조에 삽입한 뒤 번 자료구조에서 원소를 pop한다. 그때 pop된 원소를 이라 한다.
  • 을 리턴한다.

도현이는 길이 의 수열 를 가져와서 수열의 원소를 앞에서부터 차례대로 queuestack에 삽입할 것이다. 이전에 삽입한 결과는 남아 있다. (예제  참고)

queuestack에 넣을 원소들이 주어졌을 때, 해당 원소를 넣은 리턴값을 출력하는 프로그램을 작성해보자.

입력

첫째 줄에 queuestack을 구성하는 자료구조의 개수 이 주어진다. (1≤N≤100000)

둘째 줄에 길이 의 수열 가 주어진다. 번 자료구조가 큐라면 , 스택이라면 이다.

셋째 줄에 길이 의 수열 가 주어진다. 번 자료구조에 들어 있는 원소이다. (1≤B(i)≤1000000000)

넷째 줄에 삽입할 수열의 길이 이 주어진다. (1≤M≤100000)

다섯째 줄에 queuestack에 삽입할 원소를 담고 있는 길이 의 수열 가 주어진다. (1≤C(i)≤1000000000)

입력으로 주어지는 모든 수는 정수이다.

출력

수열 의 원소를 차례대로 queuestack에 삽입했을 때의 리턴값을 공백으로 구분하여 출력한다.

예제 입력 1

4
0 1 1 0
1 2 3 4
3
2 4 7

예제 출력 1

4 1 2

각 상태에 대한 큐스택 내부를 표현하면 다음과 같다.

  • 초기 상태 : [1,2,3,4]
  • 첫 번째 원소 삽입 : [2,2,3,1]
  • 두 번째 원소 삽입 : [4,2,3,2]
  • 세 번째 원소 삽입 : [7,2,3,4]

예제 입력 2

5
1 1 1 1 1
1 2 3 4 5
3
1 3 5

예제 출력 2

1 3 5

더보기

Solution

#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>

int main(void)
{
	int N, *B=NULL, M, *C=NULL, count=0;
	bool *A=NULL;

	scanf("%d", &N);
	A=(bool *)malloc(N*sizeof(bool));
	B=(int *)malloc(N*sizeof(int));

	for(int n=0;n<N;n++)
		scanf("%d", &A[n]);
	for(int n=0;n<N;n++)
		scanf("%d", &B[n]);

	scanf("%d", &M);
	C=(int *)malloc(M*sizeof(int));
	for(int m=0;m<M;m++)
		scanf("%d", &C[m]);

	for(int n=N-1;n>=0&&count<M;n--)
		if(!A[n])
		{
			count++;
			printf("%d ", B[n]);
		}
	for(int m=0;m<M&&count<M;m++)
	{
		count++;
		printf("%d ", C[m]);
	}
	printf("\n");

	return 0;
}
더보기

Solution

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb=new StringBuilder();
		StringTokenizer st;

		int count=0, temp;
		int N=Integer.parseInt(br.readLine());
		boolean[] A=new boolean[N];
		int[] B=new int[N];
		
		st=new StringTokenizer(br.readLine());
		for(int n=0;n<N;n++) {
			temp=Integer.parseInt(st.nextToken());
			A[n]=temp==1;
		}
		st=new StringTokenizer(br.readLine());
		for(int n=0;n<N;n++)
			B[n]=Integer.parseInt(st.nextToken());
		
		int M=Integer.parseInt(br.readLine());
		int[] C=new int[M];
		st=new StringTokenizer(br.readLine());
		for(int m=0;m<M;m++)
			C[m]=Integer.parseInt(st.nextToken());
		
		for(int n=N-1;n>=0&&count<M;n--)
			if(!A[n]) {
				count++;
				sb.append(B[n]+" ");
			}
		for(int m=0;m<M&&count<M;m++) {
			count++;
			sb.append(C[m]+" ");
		}
		
		System.out.println(sb.toString());
	}
}
728x90

+ Recent posts