크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸, 왼쪽에서부터 c번째 칸을 의미한다. r과 c는 1부터 시작한다.

이 도시에 사는 사람들은 치킨을 매우 좋아한다. 따라서, 사람들은 "치킨 거리"라는 말을 주로 사용한다. 치킨 거리는 집과 가장 가까운 치킨집 사이의 거리이다. 즉, 치킨 거리는 집을 기준으로 정해지며, 각각의 집은 치킨 거리를 가지고 있다. 도시의 치킨 거리는 모든 집의 치킨 거리의 합이다.

임의의 두 칸 (r1, c1)과 (r2, c2) 사이의 거리는 |r1-r2| + |c1-c2|로 구한다.

예를 들어, 아래와 같은 지도를 갖는 도시를 살펴보자.

0 2 0 1 0
1 0 1 0 0
0 0 0 0 0
0 0 0 1 1
0 0 0 1 2

0은 빈 칸, 1은 집, 2는 치킨집이다.

(2, 1)에 있는 집과 (1, 2)에 있는 치킨집과의 거리는 |2-1| + |1-2| = 2, (5, 5)에 있는 치킨집과의 거리는 |2-5| + |1-5| = 7이다. 따라서, (2, 1)에 있는 집의 치킨 거리는 2이다.

(5, 4)에 있는 집과 (1, 2)에 있는 치킨집과의 거리는 |5-1| + |4-2| = 6, (5, 5)에 있는 치킨집과의 거리는 |5-5| + |4-5| = 1이다. 따라서, (5, 4)에 있는 집의 치킨 거리는 1이다.

이 도시에 있는 치킨집은 모두 같은 프랜차이즈이다. 프렌차이즈 본사에서는 수익을 증가시키기 위해 일부 치킨집을 폐업시키려고 한다. 오랜 연구 끝에 이 도시에서 가장 수익을 많이 낼 수 있는  치킨집의 개수는 최대 M개라는 사실을 알아내었다.

도시에 있는 치킨집 중에서 최대 M개를 고르고, 나머지 치킨집은 모두 폐업시켜야 한다. 어떻게 고르면, 도시의 치킨 거리가 가장 작게 될지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N(2 ≤ N ≤ 50)과 M(1 ≤ M ≤ 13)이 주어진다.

둘째 줄부터 N개의 줄에는 도시의 정보가 주어진다.

도시의 정보는 0, 1, 2로 이루어져 있고, 0은 빈 칸, 1은 집, 2는 치킨집을 의미한다. 집의 개수는 2N개를 넘지 않으며, 적어도 1개는 존재한다. 치킨집의 개수는 M보다 크거나 같고, 13보다 작거나 같다.

출력

첫째 줄에 폐업시키지 않을 치킨집을 최대 M개를 골랐을 때, 도시의 치킨 거리의 최솟값을 출력한다.

예제 입력 1

5 3
0 0 1 0 0
0 0 2 0 1
0 1 2 0 0
0 0 1 0 0
0 0 0 0 2

예제 출력 1

5

예제 입력 2

5 2
0 2 0 1 0
1 0 1 0 0
0 0 0 0 0
2 0 0 1 1
2 2 0 1 2

예제 출력 2

10

예제 입력 3

5 1
1 2 0 0 0
1 2 0 0 0
1 2 0 0 0
1 2 0 0 0
1 2 0 0 0

예제 출력 3

11

예제 입력 4

5 1
1 2 0 2 1
1 2 0 2 1
1 2 0 2 1
1 2 0 2 1
1 2 0 2 1

예제 출력 4

32

더보기

Solution

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

int abs(int x)
{
	return x>0?x:-x;
}

int chicken_distance(int **chicken,int **house,int chicken_count,int house_count,int M,int current,int left)
{
	if(left==0 || chicken_count==M)
	{
		int sum=0;

		for(int i=0;i<house_count;i++)
		{
			int distance=99999999;

			for(int j=0;j<chicken_count;j++)
				if(chicken[j][0]!=-1 && chicken[j][1]!=-1)
					distance=abs(house[i][0]-chicken[j][0])+abs(house[i][1]-chicken[j][1])<distance?abs(house[i][0]-chicken[j][0])+abs(house[i][1]-chicken[j][1]):distance;

			sum+=distance;
		}

		return sum;
	}

	if(current+left<chicken_count)
	{
		int best=999999999;
		for(int i=current+1;i<chicken_count;i++)
		{
			int x=chicken[i][0], y=chicken[i][1];
			chicken[i][0]=chicken[i][1]=-1;

			int next=chicken_distance(chicken,house,chicken_count,house_count,M,i,left-1);
			best=next<best?next:best;
			chicken[i][0]=x;
			chicken[i][1]=y;
		}

		return best;
	}

	return 999999999;
}

int main(void)
{
	int N, M, **chicken=NULL, **map=NULL, **house=NULL, chicken_count=0, house_count=0;

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

	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			scanf("%d", &map[i][j]);
			chicken_count+=map[i][j]==2;
			house_count+=map[i][j]==1;
		}

	chicken=(int **)malloc(chicken_count*sizeof(int *));
	for(int i=0;i<chicken_count;i++)
		chicken[i]=(int *)malloc(2*sizeof(int));

	chicken_count=0;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			if(map[i][j]==2)
			{
				chicken[chicken_count][0]=i;
				chicken[chicken_count][1]=j;
				chicken_count++;
			}

	house=(int **)malloc(house_count*sizeof(int *));
	for(int i=0;i<house_count;i++)
		house[i]=(int *)malloc(2*sizeof(int));

	house_count=0;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			if(map[i][j]==1)
			{
				house[house_count][0]=i;
				house[house_count][1]=j;
				house_count++;
			}

	printf("%d\n", chicken_distance(chicken,house,chicken_count,house_count,M,-1,chicken_count-M));
	for(int i=0;i<house_count;i++)
		free(house[i]);
	free(house);
	for(int i=0;i<chicken_count;i++)
		free(chicken[i]);
	free(chicken);
	for(int i=0;i<N;i++)
		free(map[i]);
	free(map);
	return 0;
}
728x90

문제

N+1개의 I와 N개의 O로 이루어져 있으면, I와 O이 교대로 나오는 문자열을 P(N)이라고 한다.

  • P(1) IOI
  • P(2) IOIOI
  • P(3) IOIOIOI
  • P(N) IOIOI...OI (O가 N개)

I와 O로만 이루어진 문자열 S와 정수 N이 주어졌을 때, S안에 P(N)이 몇 군데 포함되어 있는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. 둘째 줄에는 S의 길이 M이 주어지며, 셋째 줄에 S가 주어진다.

출력

S에 P(N)이 몇 군데 포함되어 있는지 출력한다.

제한

  • 1 ≤ N ≤ 1,000,000
  • 2N+1 ≤ M ≤ 1,000,000
  • S는 I와 O로만 이루어져 있다.

서브태스크

번호 배점 제한
1 50 N ≤ 100, M ≤ 10 000.
2 50 추가적인 제약 조건이 없다.

예제 입력 1

1
13
OOIOIOIOIIOII

예제 출력 1

4
  • OOIOIOIOIIOII
  • OOIOIOIOIIOII
  • OOIOIOIOIIOII
  • OOIOIOIOIIOII

예제 입력 2

2
13
OOIOIOIOIIOII

예제 출력 2

2
  • OOIOIOIOIIOII
  • OOIOIOIOIIOII

더보기

Solution

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

int main(void)
{
	int N, M, len=0, count=0;
	char *S=NULL;

	scanf("%d", &N);
	scanf("%d", &M);
	S=(char *)calloc(M+1,sizeof(char));

	scanf("%s", S);

	for(int i=2;i<M;i++)
		if(S[i]=='I')
		{
			if(S[i-1]=='O' && S[i-2]=='I')
			{
				len++;
				if(len>=N)
					count++;
			}
			else
				len=0;
		}

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

수빈이는 TV를 보고 있다. 수빈이는 채널을 돌리려고 했지만, 버튼을 너무 세게 누르는 바람에, 일부 숫자 버튼이 고장났다.

리모컨에는 버튼이 0부터 9까지 숫자, +와 -가 있다. +를 누르면 현재 보고있는 채널에서 +1된 채널로 이동하고, -를 누르면 -1된 채널로 이동한다. 채널 0에서 -를 누른 경우에는 채널이 변하지 않고, 채널은 무한대 만큼 있다.

수빈이가 지금 이동하려고 하는 채널은 N이다. 어떤 버튼이 고장났는지 주어졌을 때, 채널 N으로 이동하기 위해서 버튼을 최소 몇 번 눌러야하는지 구하는 프로그램을 작성하시오. 

수빈이가 지금 보고 있는 채널은 100번이다.

입력

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다.  둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼이 주어지며, 같은 버튼이 여러 번 주어지는 경우는 없다.

출력

첫째 줄에 채널 N으로 이동하기 위해 버튼을 최소 몇 번 눌러야 하는지를 출력한다.

예제 입력 1

5457
3
6 7 8

예제 출력 1

6

예제 입력 2

100
5
0 1 2 3 4

예제 출력 2

0

예제 입력 3

500000
8
0 2 3 4 6 7 8 9

예제 출력 3

11117

예제 입력 4

100
3
1 0 5

예제 출력 4

0

예제 입력 5

14124
0

예제 출력 5

5

예제 입력 6

1
9
1 2 3 4 5 6 7 8 9

예제 출력 6

2

예제 입력 7

80000
2
8 9

예제 출력 7

2228

더보기

Solution

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

int abs(int N)
{
	return N>0?N:-N;
}

int main(void)
{
	int N, M, num, hundred, best=999999999, count=0;
	bool normal[10];

	for(int i=0;i<10;i++)
		normal[i]=true;

	scanf("%d", &N);
	scanf("%d", &M);
	for(int m=0;m<M;m++)
	{
		scanf("%d", &num);
		normal[num]=false;
	}

	hundred=abs(N-100);

	if(hundred<2 || M==10)
	{
		printf("%d\n", hundred);
		return 0;
	}

	for(int n=0;n<1000000;n++)
	{
		bool able=true;
		count=0;
		num=n;

		if(num==0)
			for(int i=0;i<10;i++)
				if(normal[i])
				{
					count=i+1;
					break;
				}
		while(num>0)
		{
			if(!normal[num%10])
			{
				able=false;
				break;
			}
			count++;
			num/=10;
		}

		if(able)
			best=count+abs(N-n)>best?best:count+abs(N-n);
	}

	printf("%d\n", best>hundred?hundred:best);
	return 0;
}
728x90

팀 레드시프트는 대회 준비를 하다가 지루해져서 샌드박스 게임인 ‘마인크래프트’를 켰다. 마인크래프트는 1 × 1 × 1(세로, 가로, 높이) 크기의 블록들로 이루어진 3차원 세계에서 자유롭게 땅을 파거나 집을 지을 수 있는 게임이다.

목재를 충분히 모은 lvalue는 집을 짓기로 하였다. 하지만 고르지 않은 땅에는 집을 지을 수 없기 때문에 땅의 높이를 모두 동일하게 만드는 ‘땅 고르기’ 작업을 해야 한다.

lvalue는 세로 N, 가로 M 크기의 집터를 골랐다. 집터 맨 왼쪽 위의 좌표는 (0, 0)이다. 우리의 목적은 이 집터 내의 땅의 높이를 일정하게 바꾸는 것이다. 우리는 다음과 같은 두 종류의 작업을 할 수 있다.

  1. 좌표 (i, j)의 가장 위에 있는 블록을 제거하여 인벤토리에 넣는다.
  2. 인벤토리에서 블록 하나를 꺼내어 좌표 (i, j)의 가장 위에 있는 블록 위에 놓는다.

1번 작업은 2초가 걸리며, 2번 작업은 1초가 걸린다. 밤에는 무서운 몬스터들이 나오기 때문에 최대한 빨리 땅 고르기 작업을 마쳐야 한다. ‘땅 고르기’ 작업에 걸리는 최소 시간과 그 경우 땅의 높이를 출력하시오.

단, 집터 아래에 동굴 등 빈 공간은 존재하지 않으며, 집터 바깥에서 블록을 가져올 수 없다. 또한, 작업을 시작할 때 인벤토리에는 B개의 블록이 들어 있다. 땅의 높이는 256블록을 초과할 수 없으며, 음수가 될 수 없다.

입력

첫째 줄에 N, M, B가 주어진다. (1 ≤ M, N ≤ 500, 0 ≤ B ≤ 6.4 × 10^7)

둘째 줄부터 N개의 줄에 각각 M개의 정수로 땅의 높이가 주어진다. (i + 2)번째 줄의 (+ 1)번째 수는 좌표 (i, j)에서의 땅의 높이를 나타낸다. 땅의 높이는 256보다 작거나 같은 자연수 또는 0이다.

출력

첫째 줄에 땅을 고르는 데 걸리는 시간과 땅의 높이를 출력하시오. 답이 여러 개 있다면 그중에서 땅의 높이가 가장 높은 것을 출력하시오.

예제 입력 1

3 4 99
0 0 0 0
0 0 0 0
0 0 0 1

예제 출력 1

2 0

예제 입력 2

3 4 1
64 64 64 64
64 64 64 64
64 64 64 63

예제 출력 2

1 64

 

인벤토리에 블록이 하나 있기 때문에, 맨 오른쪽 아래에 블록을 하나 채우면 된다.

예제 입력 3

3 4 0
64 64 64 64
64 64 64 64
64 64 64 63

예제 출력 3

22 63

더보기

Solution

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

int main(void)
{
	int N, M, B, **land=NULL, min=256, max=0, best=2100000000, best_height;

	scanf("%d%d%d", &N, &M, &B);
	land=(int **)malloc(N*sizeof(int *));
	for(int n=0;n<N;n++)
		land[n]=(int *)malloc(M*sizeof(int));

	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++)
		{
			scanf("%d", &land[i][j]);
			if(land[i][j]>max)
				max=land[i][j];
			if(land[i][j]<min)
				min=land[i][j];
		}

	for(int count=min;count<=max;count++)
	{
		int sec=0, left=B;
		bool able=true;

		for(int i=0;i<N;i++)
			for(int j=0;j<M;j++)
				if(land[i][j]>count)
				{
					sec+=2*(land[i][j]-count);
					left+=land[i][j]-count;
				}

		for(int i=0;i<N;i++)
		{
			for(int j=0;j<M;j++)				
				if(land[i][j]<count)
				{
					sec+=count-land[i][j];
					if(count-land[i][j]>left)
					{
						able=false;
						break;
					}
					left-=count-land[i][j];
				}
			if(!able)
				break;
		}

		if(able && sec<=best)
		{
			best=sec;
			best_height=count;
		}
	}

	printf("%d %d\n", best, best_height);
	for(int n=0;n<N;n++)
		free(land[n]);
	free(land);
	return 0;
}
728x90

문제

APC에 온 것을 환영한다. 만약 여러분이 학교에서 자료구조를 수강했다면 해시 함수에 대해 배웠을 것이다. 해시 함수란 임의의 길이의 입력을 받아서 고정된 길이의 출력을 내보내는 함수로 정의한다. 해시 함수는 무궁무진한 응용 분야를 갖는데, 대표적으로 자료의 저장과 탐색에 쓰인다.

이 문제에서는 여러분이 앞으로 유용하게 쓸 수 있는 해시 함수를 하나 가르쳐주고자 한다. 먼저, 편의상 입력으로 들어오는 문자열에는 영문 소문자(a, b, ..., z)로만 구성되어있다고 가정하자. 영어에는 총 26개의 알파벳이 존재하므로 a에는 1, b에는 2, c에는 3, ..., z에는 26으로 고유한 번호를 부여할 수 있다. 결과적으로 우리는 하나의 문자열을 수열로 변환할 수 있다. 예를 들어서 문자열 "abba"은 수열 1, 2, 2, 1로 나타낼 수 있다.

해시 값을 계산하기 위해서 우리는 문자열 혹은 수열을 하나의 정수로 치환하려고 한다. 간단하게는 수열의 값을 모두 더할 수도 있다. 해시 함수의 정의에서 유한한 범위의 출력을 가져야 한다고 했으니까 적당히 큰 수 M으로 나눠주자. 짜잔! 해시 함수가 완성되었다. 이를 수식으로 표현하면 아래와 같다.

해시 함수의 입력으로 들어올 수 있는 문자열의 종류는 무한하지만 출력 범위는 정해져있다. 다들 비둘기 집의 원리에 대해서는 한 번쯤 들어봤을 것이다. 그 원리에 의하면 서로 다른 문자열이더라도 동일한 해시 값을 가질 수 있다. 이를 해시 충돌이라고 하는데, 좋은 해시 함수는 최대한 충돌이 적게 일어나야 한다. 위에서 정의한 해시 함수는 알파벳의 순서만 바꿔도 충돌이 일어나기 때문에 나쁜 해시 함수이다. 그러니까 조금 더 개선해보자.

어떻게 하면 순서가 달라졌을때 출력값도 달라지게 할 수 있을까? 머리를 굴리면 수열의 각 항마다 고유한 계수를 부여하면 된다는 아이디어를 생각해볼 수 있다. 가장 대표적인 방법은 항의 번호에 해당하는 만큼 특정한 숫자를 거듭제곱해서 곱해준 다음 더하는 것이 있다. 이를 수식으로 표현하면 아래와 같다.

보통 r과 M은 서로소인 숫자로 정하는 것이 일반적이다. 우리가 직접 정하라고 하면 힘들테니까 r의 값은 26보다 큰 소수인 31로 하고 M의 값은 1234567891(놀랍게도 소수이다!!)로 하자.

이제 여러분이 할 일은 위 식을 통해 주어진 문자열의 해시 값을 계산하는 것이다. 그리고 이 함수는 간단해 보여도 자주 쓰이니까 기억해뒀다가 잘 써먹도록 하자.

입력

첫 줄에는 문자열의 길이 L이 들어온다. 둘째 줄에는 영문 소문자로만 이루어진 문자열이 들어온다.

입력으로 주어지는 문자열은 모두 알파벳 소문자로만 구성되어 있다.

출력

문제에서 주어진 해시함수와 입력으로 주어진 문자열을 사용해 계산한 해시 값을 정수로 출력한다.

Small (50점)

  • 1 ≤ L ≤ 5

Large (50점)

  • 1 ≤ L ≤ 50

예제 입력 1

5
abcde

예제 출력 1

4739715

예제 입력 2

3
zzz

예제 출력 2

25818

예제 입력 3

1
i

예제 출력 3

9

힌트

예제 1: abcde의 해시 값은 1 × 310 + 2 × 311 + 3 × 312 + 4 × 313 + 5 × 314 = 1 + 62 + 2883 + 119164 + 4617605 = 4739715이다.

예제 2: zzz의 해시 값은 26 × 310 + 26 × 311 + 26 × 312 = 26 + 806 + 24986 = 25818이다.


더보기

Solution

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

int main(void)
{
	long long L, num, hash=0, mul=1;
	char *str=NULL;

	scanf("%lld", &L);
	str=(char *)calloc(L,sizeof(char));
	scanf("%s", str);

	for(long long i=0;i<L;i++)
	{
		num=str[i]-'a'+1;

		num=mul*num;
		num%=1234567891;

		hash+=num;
		hash%=1234567891;

		mul*=31;
		mul%=1234567891;
	}

	printf("%lld\n", hash);
	free(str);
	return 0;
}
728x90

N×N개의 수가 N×N 크기의 표에 채워져 있다. (x1, y1)부터 (x2, y2)까지 합을 구하는 프로그램을 작성하시오. (x, y)는 x행 y열을 의미한다.

예를 들어, N = 4이고, 표가 아래와 같이 채워져 있는 경우를 살펴보자.

1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7

여기서 (2, 2)부터 (3, 4)까지 합을 구하면 3+4+5+4+5+6 = 27이고, (4, 4)부터 (4, 4)까지 합을 구하면 7이다.

표에 채워져 있는 수와 합을 구하는 연산이 주어졌을 때, 이를 처리하는 프로그램을 작성하시오.

입력

첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네 개의 정수 x1, y1, x2, y2 가 주어지며, (x1, y1)부터 (x2, y2)의 합을 구해 출력해야 한다. 표에 채워져 있는 수는 1,000보다 작거나 같은 자연수이다. (x1 ≤ x2, y1 ≤ y2)

출력

총 M줄에 걸쳐 (x1, y1)부터 (x2, y2)까지 합을 구해 출력한다.

예제 입력 1

4 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
2 2 3 4
3 4 3 4
1 1 4 4

예제 출력 1

27
6
64

예제 입력 2

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

예제 출력 2

1
2
3
4

더보기

Solution

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

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

	scanf("%d%d", &N, &M);
	arr=(int **)malloc((N+1)*sizeof(int *));
	accumulate=(int **)malloc((N+1)*sizeof(int *));
	for(int n=0;n<=N;n++)
	{
		arr[n]=(int *)calloc(N+1,sizeof(int));
		accumulate[n]=(int *)calloc(N+1,sizeof(int));
	}

	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
		{
			scanf("%d", &arr[i][j]);
			accumulate[i][j]=arr[i][j]+accumulate[i-1][j]+accumulate[i][j-1]-accumulate[i-1][j-1];
		}

	for(int m=0;m<M;m++)
	{
		int x1, x2, y1, y2;

		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		printf("%d\n", accumulate[x2][y2]-accumulate[x2][y1-1]-accumulate[x1-1][y2]+accumulate[x1-1][y1-1]);
	}

	for(int n=0;n<=N;n++)
	{
		free(arr[n]);
		free(accumulate[n]);
	}
	free(arr);
	free(accumulate);
	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 IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb=new StringBuilder();
		StringTokenizer st;

		st=new StringTokenizer(br.readLine());
		int N=Integer.parseInt(st.nextToken());
		int M=Integer.parseInt(st.nextToken());
		int[][] arr=new int[N+1][N+1];
		int[][] accumulate=new int[N+1][N+1];
		int x1, x2, y1, y2;
		
		for(int i=1;i<=N;i++) {
			st=new StringTokenizer(br.readLine());
			for(int j=1;j<=N;j++) {
				arr[i][j]=Integer.parseInt(st.nextToken());
				accumulate[i][j]=arr[i][j]+accumulate[i-1][j]+accumulate[i][j-1]-accumulate[i-1][j-1];
			}
		}
		
		for(int m=0;m<M;m++) {
			st=new StringTokenizer(br.readLine());
			x1=Integer.parseInt(st.nextToken());
			y1=Integer.parseInt(st.nextToken());
			x2=Integer.parseInt(st.nextToken());
			y2=Integer.parseInt(st.nextToken());
			
			sb.append(accumulate[x2][y2]-accumulate[x2][y1-1]-accumulate[x1-1][y2]+accumulate[x1-1][y1-1]+"\n");
		}

		System.out.println(sb.toString());
	}
}

 

728x90

수 N개가 주어졌을 때, i번째 수부터 j번째 수까지 합을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j가 주어진다.

출력

총 M개의 줄에 입력으로 주어진 i번째 수부터 j번째 수까지 합을 출력한다.

제한

  • 1 ≤ N ≤ 100,000
  • 1 ≤ M ≤ 100,000
  • 1 ≤ i ≤ j ≤ N

예제 입력 1

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

예제 출력 1

12
9
1

더보기

Solution

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

int main(void)
{
	int N, M, i, j, *arr=NULL, *accumulate=NULL;

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

	for(int n=0;n<N;n++)
	{
		scanf("%d", &arr[n]);
		accumulate[n]=arr[n];
	}
	for(int n=1;n<N;n++)
		accumulate[n]+=accumulate[n-1];

	for(int m=0;m<M;m++)
	{
		scanf("%d%d", &i, &j);
		printf("%d\n", accumulate[j-1]-accumulate[i-1]+arr[i-1]);
	}

	free(arr);
	free(accumulate);
	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 IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb=new StringBuilder();
		StringTokenizer st;

		st=new StringTokenizer(br.readLine());
		int N=Integer.parseInt(st.nextToken());
		int M=Integer.parseInt(st.nextToken());
		int[] arr=new int[N];
		int[] accumulate=new int[N];
		int i, j;
		
		st=new StringTokenizer(br.readLine());
		accumulate[0]=arr[0]=Integer.parseInt(st.nextToken());
		for(int n=1;n<N;n++) {
			arr[n]=Integer.parseInt(st.nextToken());
			accumulate[n]=accumulate[n-1]+arr[n];
		}

		for(int m=0;m<M;m++) {
			st=new StringTokenizer(br.readLine());
			i=Integer.parseInt(st.nextToken());
			j=Integer.parseInt(st.nextToken());
			sb.append(accumulate[j-1]-accumulate[i-1]+arr[i-1]+"\n");
		}

		System.out.println(sb.toString());
	}
}

 

728x90

세계는 균형이 잘 잡혀있어야 한다. 양과 음, 빛과 어둠 그리고 왼쪽 괄호와 오른쪽 괄호처럼 말이다.

정민이의 임무는 어떤 문자열이 주어졌을 때, 괄호들의 균형이 잘 맞춰져 있는지 판단하는 프로그램을 짜는 것이다.

문자열에 포함되는 괄호는 소괄호("()") 와 대괄호("[]")로 2종류이고, 문자열이 균형을 이루는 조건은 아래와 같다.

  • 모든 왼쪽 소괄호("(")는 오른쪽 소괄호(")")와만 짝을 이뤄야 한다.
  • 모든 왼쪽 대괄호("[")는 오른쪽 대괄호("]")와만 짝을 이뤄야 한다.
  • 모든 오른쪽 괄호들은 자신과 짝을 이룰 수 있는 왼쪽 괄호가 존재한다.
  • 모든 괄호들의 짝은 1:1 매칭만 가능하다. 즉, 괄호 하나가 둘 이상의 괄호와 짝지어지지 않는다.
  • 짝을 이루는 두 괄호가 있을 때, 그 사이에 있는 문자열도 균형이 잡혀야 한다.

정민이를 도와 문자열이 주어졌을 때 균형잡힌 문자열인지 아닌지를 판단해보자.

입력

하나 또는 여러줄에 걸쳐서 문자열이 주어진다. 각 문자열은 영문 알파벳, 공백, 소괄호("( )") 대괄호("[ ]")등으로 이루어져 있으며, 길이는 100글자보다 작거나 같다. 각 줄은 마침표(".")로 끝난다.

입력의 종료조건으로 맨 마지막에 점 하나(".")가 들어온다.

출력

각 줄마다 해당 문자열이 균형을 이루고 있으면 "yes"를, 아니면 "no"를 출력한다.

예제 입력 1

So when I die (the [first] I will see in (heaven) is a score list).
[ first in ] ( first out ).
Half Moon tonight (At least it is better than no Moon at all].
A rope may form )( a trail in a maze.
Help( I[m being held prisoner in a fortune cookie factory)].
([ (([( [ ] ) ( ) (( ))] )) ]).
 .
.

예제 출력 1

yes
yes
no
no
no
yes
yes

힌트

7번째의 " ."와 같이 괄호가 하나도 없는 경우도 균형잡힌 문자열로 간주할 수 있다.


더보기

Solution

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

int main(void)
{
	char str[101]={'\0', };

	gets(str);
	while(strcmp(str,".")!=0)
	{
		int check[101]={0, }, current=0;
		bool able=true;

		for(int i=0;str[i]!='.';i++)
		{
			switch(str[i])
			{
				case '(':
					check[current++]=1;
					break;
				case '[':
					check[current++]=2;
					break;
				case ')':
					if(current==0)
						able=false;
					else if(check[--current]!=1)
						able=false;
					break;
				case ']':
					if(current==0)
						able=false;
					else if(check[--current]!=2)
						able=false;
					break;
			}
			if(!able)
				break;
		}

		printf("%s\n", able&&current==0?"yes":"no");

		for(int i=0;i<101;i++)
			str[i]='\0';
		gets(str);
	}

	return 0;
}
728x90

+ Recent posts