반응형

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

 

17141번: 연구소 2

인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 승원이는 연구소의 특정 위치에 바이러스 M개를 놓을 것이고, 승원이의 신호와 동시에 바이

www.acmicpc.net

1.문제설명

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

N*N 정사각형 배열이 주어진다. 1은 바이러스가 지나갈 수 없는 벽을 의미한다.

m은 바이러스를 놓을 수 있는 개수이고, 2는 바이러스를 놓을 수 있는 공간이다.

2가 바이러스가 놓여진 게 아니라 놓을 수 있는 공간인 점이 중요하다.

m개의 바이러스를 2가 쓰여진 공간에 두었을 때 

벽을 제외한 모든 공간에 바이러스를 퍼트린다면 

바이러스를 퍼트리는데 걸리는 최소 시간을 구해야한다.

그 최소 시간을 출력해야한다.

 

만약 바이러스 m개를 어떻게 두어도 벽을 제외한 모든 공간에 바이러스를 퍼트리지 못한다면

-1을 출력한다.

 

 

2.접근방법[알고리즘]

1. 백트래킹으로 바이러스 놓는 칸 m개 선택
2. m개를 선택했을 때 바이러스 다 퍼트릴 수 있는 지 BFS해보고 퍼트릴 수 있다면 시간을 구한다.
3. m개를 선택하는 모든 방법에 대하여 시간을 구해보고 최소 시간을 뽑는다.
4. 어떤 방법으로도 바이러스를 모든 공간에 퍼트릴 수 없다면 -1을 출력한다.

 

 

 

 

 

 

3.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;

int n, m, arr[51][51], ans=INT_MAX;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
vector<pair<int, int > > virus;
queue<pair<int, int> > Q;
//1. 바이러스 놓는 칸 m개 선택
//2. 바이러스 다 퍼트렸는지 확인
//3. 다 퍼트렸다면 최소시간 확인
//4. 다 퍼트린게 없다면 -1 출력

void print() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (arr[i][j] == -1) cout << '-' << ' ';
			else cout << arr[i][j] <<' ';
		}
		cout << '\n';
	}
	cout << "------------\n";

}

int check() {
	int minute = 0;
	//print();

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (arr[i][j] == -1) continue;

			if (arr[i][j] == 0) {
				return INT_MAX;
			}
			else {
				minute = max(arr[i][j], minute);
			}
		}
	}
	return minute;
}

void BFS() {

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (arr[i][j] == 1) {
				Q.push({ i,j });
			}
		}
	}

	while (!Q.empty()) {
		int x = Q.front().first;
		int y = Q.front().second;
		Q.pop();


		for (int i = 0; i < 4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
			if (arr[nx][ny] == 0) {
				arr[nx][ny] = arr[x][y] + 1;
				Q.push({ nx,ny });
			}
		}
	}
}

void initialize() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (arr[i][j] > 1) {
				arr[i][j] = 0;
			}
		}
	}
}

void DFS(int cur, int L) {
	if (L == m) {	
		BFS();
		ans = min(ans, check());
		initialize();
	}
	else {
		for (int i = cur; i < virus.size(); i++) {
			//바이러스는 arr에서 1로 체크해준다.
			int x = virus[i].first;
			int y = virus[i].second;
			if (arr[x][y] == 0) {
				arr[x][y] = 1;
				DFS(i + 1, L + 1);
				arr[x][y] = 0;
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;

	queue<pair<int, int > > Q;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 1) {
				arr[i][j] = -1;
			}
			if (arr[i][j] == 2) {
				arr[i][j] = 0;
				virus.push_back({ i,j });
			}
		}
	}


	DFS(0,0);

	if (ans == INT_MAX) {
		cout << -1;
	}
	else {
		cout << ans-1;
	}

}

백준 17141번 연구소 문제 메모리 및 시간

 

 

 

반응형
반응형

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

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

www.acmicpc.net

1.문제설명

7 7
2 0 0 0 1 1 0
0 0 1 0 1 2 0
0 1 1 0 1 0 0
0 1 0 0 0 0 0
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 1 0 0 0 0 0

0은 빈공간이고 1은 벽이고 2는 바이러스다.

바이러스는 상하좌우로 퍼질수 있고 벽은 통과할 수 없다.

벽을 3개 설치해서 바이러스가 퍼지지 않는 빈공간(0)의 최대 개수를 구해야 하는 문제다.

 

 

2.접근방법[알고리즘]

1.추가로 벽(1)을 세개 설치해야한다.

2.벽을 세개 설치 한 뒤 바이러스가 퍼진 결과를 구한다.

3. 그 결과에서 0의 개수를 구해준다.

4. 0의 개수를 저장해주며 벽을 다르게 설치할 때마다 0의 개수를 구하고 최댓값을 출력한다.

 

 

이렇게 풀기 위해서

벽을 세개 설치 하는 걸 DFS함수로 구현했다.

벽을 세개 설치하면 그 때 바이러스를 퍼트린 후 0의 갯수를 리턴한다.

DFS를 돌면서 ans변수에 최댓값을 저장해준다.

void DFS(int x, int y, int L) {
	if (L == 3) {
		//바이러스 BFS 돌고 0 갯수 새기
		ans = max(ans, Count());
	}
	else {
		// 벽 만들기 백트래킹
		for (int i = x; i < n; i++, y=0) {
			for (int j = y; j < m; j++) {
				if (arr[i][j] == 0) {
					arr[i][j] = 1;
					DFS(i, j, L + 1);
					arr[i][j] = 0;
				}
			}
		}
	}
}

2중 for문을 왜 저렇게 쓰는지 이해가 안가면

https://dingcoding.tistory.com/85

 

백준 15684번 : 사다리 조작 - DFS, 백트래킹, 가지치기의 중요성

https://www.acmicpc.net/problem/15684 15684번: 사다리 조작 사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선

dingcoding.tistory.com

위 글의 3.문제풀이코드 부분에 설명을 보면 좋다.

 

 

 

 

벽을 설치한뒤 0의 갯수를 구하는 Count 함수를 구현했다.

int Count() {
	BFS();
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (arr[i][j] == 0) cnt++;
			else if (arr[i][j] == 2) {
				//arr배열을 재사용하기위해 BFS 돌아서 바이러스가 퍼진 영역을 
				//다시 0으로 만들어준다.
				arr[i][j] = 0;
			}
		}
	}
	//바이러스 초기화 arr 원상태로 만들어줌
	for (int i = 0; i < virus.size(); i++) 
		arr[virus[i].first][virus[i].second] = 2;
	return cnt;
}

 

Count를 다 하고 나면 arr배열에 초기 입력값을 그대로 저장해준다.

 

 

 

 

3.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;

int n, m, arr[10][10], ans;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

vector<pair<int, int> > virus;
queue<pair<int, int > > Q;

// 바이러스 퍼트리는 함수 
void BFS() {
	for (int i = 0; i < virus.size(); i++) {
		Q.push({ virus[i].first, virus[i].second });
	}
	while (!Q.empty()) {
		int x = Q.front().first;
		int y = Q.front().second;
		Q.pop();
		for (int i = 0; i < 4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
			if (arr[nx][ny] == 0) {
				//바이러스가 퍼질 수 있는 곳이면 바이러스로 만들어준다.
				arr[nx][ny] = 2;
				Q.push({ nx,ny });
			}
		}
	}
}

//0 갯수 세는 함수 
int Count() {
	BFS();
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (arr[i][j] == 0) cnt++;
			else if (arr[i][j] == 2) {
				//arr배열을 재사용하기위해 BFS 돌아서 바이러스가 퍼진 영역을 
				//다시 0으로 만들어준다.
				arr[i][j] = 0;
			}
		}
	}
	//바이러스 초기화 arr 원상태로 만들어줌
	for (int i = 0; i < virus.size(); i++) 
		arr[virus[i].first][virus[i].second] = 2;
	return cnt;
}

void DFS(int x, int y, int L) {
	if (L == 3) {
		//바이러스 BFS 돌고 0 갯수 새기
		ans = max(ans, Count());
	}
	else {
		// 벽 만들기 백트래킹
		for (int i = x; i < n; i++, y=0) {
			for (int j = y; j < m; j++) {
				if (arr[i][j] == 0) {
					arr[i][j] = 1;
					DFS(i, j, L + 1);
					arr[i][j] = 0;
				}
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 2) {
				virus.push_back({ i,j });
			}
		}
	}
	DFS(0, 0, 0);
	cout << ans << '\n';
}

14502 연구소 문제 시간, 메모리 

문제풀이후기

다중 for문을 사용해 벽을 세우는 방법도 있다.

그래도 위 코드처럼 DFS를 이용해서 벽을 세우고 백트래킹해주면

더 간결한 것 같다.

 

반응형
반응형

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

 

13459번: 구슬 탈출

첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'

www.acmicpc.net

1. 문제설명

구슬이 있는 판을 상하좌우로 기울일 수 있고,10번의 기회가 있다.

빨간색 구슬만 'O'를 만나는 경우가 있다면 1을 출력하고 없으면 0을 출력한다.

빨간색구슬이 'O'를 만날 때 파란색 구슬도 'O'를 만나는 경우는 제외한다.

 

2. 알고리즘

1. 구슬 판을 기울이는 함수를 구현해야 한다. dx, dy 방향으로 움직이고 'O'이나 '#'을 만나면 멈춘다.

2. 4방향으로 구슬판을 기울이고 기울인 결과가 이전에 이미 했던 경우가 아니라면 큐에 넣어준다.

3. 기울인 결과를 check 해주는 배열에 넣어준다.

4. BFS를 10번 돌 때 까지 빨간 공이 'O를 만나는 경우가 존재하지 않으면 BFS를 종료하고 '0'을 출력한다.

 

 

 

 

3.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;
int n, m, red_x, red_y, blue_x, blue_y, cnt = 0;

char board[15][15];
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
bool vis[15][15][15][15], isend;

struct Edge {
	//c는 BFS 시행 횟수 저장 
	int a, b, c;
	Edge(int x, int y, int z) {
		a = x;
		b = y;
		c = z;
	}

};

//끝까지 이동
void move(int &nrx, int &nry, int dx, int dy, int &rcnt) {
	while (1) {
		if (board[nrx][nry] == '#') { //벽에 무조건 걸린다
			nrx -= dx;
			nry -= dy;
			rcnt--;
			break;
		}
		if (board[nrx][nry] == 'O') {
			break;
		}
		nrx += dx;
		nry += dy;
		rcnt++;
	}
}

//
//void print(int nrx, int nry, int nbx, int nby, int count) {
//	cout << "----------------\n";
//
//	for (int i = 1; i <= n; i++) {
//		for (int j = 1; j <= m; j++) {
//			if (i == nrx && j == nry) cout << 'R';
//			else if (i == nbx && j == nby) cout << "B";
//			else cout << board[i][j];
//		}
//		cout << '\n';
//	}
//	cout << "BFS CNT : "<<count << "-------------\n\n";
//}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	//Red//Blue 순
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> board[i][j];
			if (board[i][j] == 'R') {
				board[i][j] = '.';
				red_x = i;
				red_y = j;
			}
			else if (board[i][j] == 'B') {
				board[i][j] = '.';
				blue_x = i;
				blue_y = j;
			}
		}
	}
	queue<Edge> Q;
	Q.push(Edge(red_x,red_y,0));
	Q.push(Edge(blue_x,blue_y,0));
	vis[red_x][red_y][blue_x][blue_y] = 1;

	while (!Q.empty()) {
		int rx = Q.front().a;
		int ry = Q.front().b;
		Q.pop();
		int bx = Q.front().a;
		int by = Q.front().b;
		int count = Q.front().c;
		Q.pop();


		//print(rx, ry, bx, by, count);
		if (count >= 10) break;
		

		for (int i = 0; i < 4; i++) {
			int rcnt = 0, bcnt = 0;
			int nrx = rx;
			int nry = ry;
			int nbx = bx;
			int nby = by;
			move(nrx, nry, dx[i], dy[i], rcnt);
			move(nbx, nby, dx[i], dy[i], bcnt);

			if (board[nbx][nby] == 'O') {
				continue;
			}
			else if (board[nrx][nry] == 'O') {
				//print(nrx, nry, nbx, nby, count + 1);
				cout << 1 << '\n';
				isend = true;
				return 0;
			}
			else {
				if (nbx == nrx && nry == nby) {
					if (rcnt > bcnt) {
						nrx -= dx[i];
						nry -= dy[i];
					}
					else {
						nbx -= dx[i];
						nby -= dy[i];
					}
				}
				if (vis[nrx][nry][nbx][nby] == 0) {
					vis[nrx][nry][nbx][nby] = 1;
					Q.push(Edge(nrx,nry,count+1));
					Q.push(Edge(nbx,nby,count+1));
				}
			}
		}
	}

	if (!isend) {
		cout << 0;
	}
	return 0;
}

백준 13459번 구슬탈출&nbsp;

 

주석 부분을 해제하면 이동 과정을 출력해볼 수 있다.

 

문제푸는데 헷갈려서 넣어봤다.

 

구슬 이동 출력

백준 13459번 구슬탈출 구슬이동과정
백준 13459번 구슬탈출 구슬이동과정

 

 

문제풀이후기

아무래도 그동안 풀던 문제에 비해 코드 길이는 길어졌다.

코드를 함수를 잘 만들어서 중복되는 부분을 줄일수록 코드 구성을 판단하기 쉬워진다.

복잡하지만 결국 4방향에 대해 너비우선탐색을 하여

문제조건에 알맞는 결과가 있다면 종료해주는 문제였다.

다만 탐색하는 부분에 대하여 조건에 맞춰 코드를 작성해야할 필요가 있다.

반응형
반응형

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

 

2583번: 영역 구하기

첫째 줄에 M과 N, 그리고 K가 빈칸을 사이에 두고 차례로 주어진다. M, N, K는 모두 100 이하의 자연수이다. 둘째 줄부터 K개의 줄에는 한 줄에 하나씩 직사각형의 왼쪽 아래 꼭짓점의 x, y좌표값과 오

www.acmicpc.net

 

 

 

1. 문제설명

 

2583번 문제
2583번 문제

모눈 종이에 직사각형이 그려져 있을 때

직사각형이 색칠되어 있지 않은 남은 부분들의 갯수와 부분들의 넓이를 구해서

오름차순으로 정렬해 출력하면 된다.

사각형의 갯수가 곧 넓이가 된다.

 

 

 

 

 

2. 접근방법[알고리즘]

색칠된 부분을 저장하기 위해 M*N 배열을 만들어야한다.

좌표를 설정하는 걸 조심해야한다.

 

2583번 좌표설정

N, M은 7,5지만 이건 꼭짓점이고 실제로

해당 칸 마다 좌표를 부여하면 (0,0) ~ (6,4)까지만 사용 한다.

 

 

입력

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

arr[i][j]의 값에 색칠되었다면 -1을 저장하고 색칠되지 않았다면 0을 저장해준다.

색칠해줄 때도 (0,2)에서 (4,4)까지 칠해주는게 아니라 (0,2)에서 (3,3)까지 칠해주어야한다.

이유는 위와 동일하게 (4,4)는 사각형의 해당 좌표가아니라 꼭짓점이기 때문이다.

 

	//직사각형 -1로 칠하기
	for (int i = 0; i < k; i++) {
		int x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		for (int j = y1; j < y2; j++) { // y1 ~ <y2 까지 돌아야 한다
			for (int k = x1; k < x2; k++) { // x1 ~ <x2 까지 돌아야 한다
				arr[j][k] = -1;
			}
		}
	}

 

 

 

 

그리고 arr배열 값이 -1인 좌표는 BFS를 돌지 않고

arr배열이 0인 값만 탐색한다.

 

이제 arr배열을 돌면서 값이 0인 좌표를 발견하면

BFS를 실행하면서 arr 값에 사각형의 개수를 저장해준다.

 

2583번 문제

BFS 실행 코드

arr값이 0인 좌표를 발견할 때 arr 값을 1로 저장해준다. 

cnt 변수는 arr값이 0인 좌표를 발견했을 때 +1 해주어 전체 하얀 부분의 개수를 구할 수 있다.

this_area 변수는 BFS를 돌면서 0인좌표를 발견할 때마다 +1 해주어 해당 부분의 넓이를 저장해준다

그리고 Q가 empty가 되어 BFS가 끝나면 해당 하얀 부분을 다 탐색했다는 뜻이므로

this_area 변수의 값을 ans에 저장해준다.

 

이렇게 모든 좌표에대해 탐색하면 하얀 부분의 넓이를 모두 구할 수 있다.

	queue<pair<int, int> > Q;

	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (arr[i][j] == 0) {
				cnt++;
				arr[i][j] = 1;
				int this_area = 1;
				Q.push(make_pair(i, j));

				while (!Q.empty()) {
					int cur_x = Q.front().first;
					int cur_y = Q.front().second;
					Q.pop();

					for (int k = 0; k < 4; k++) {
						int nx = cur_x + dx[k];
						int ny = cur_y + dy[k];
						if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
						if (arr[nx][ny] == 0) {
							arr[nx][ny] = ++this_area;
							Q.push({ nx,ny });
						}
					}
				}
				ans.push_back(this_area);
			}
		}
	}

 

 

 

 

3.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;

int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
int n,m,k, cnt, arr[101][101];
vector<int> ans;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	//색칠영역 -1로 두고
	//-1이 아닌 곳 BFS 돌면서 넓이 구해주면 된다
	cin >> m >> n >> k;

	//직사각형 -1로 칠하기
	for (int i = 0; i < k; i++) {
		int x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		for (int j = y1; j < y2; j++) {
			for (int k = x1; k < x2; k++) {
				arr[j][k] = -1;
			}
		}
	}

	//직사각형 확인
	//cout << "------------------------\n";
	//for (int i = 0; i < m; i++) {
	//	for (int j = 0; j < n; j++) {
	//		cout << arr[i][j] << ' ';
	//	}
	//	cout << '\n';
	//}
	//cout << "-------------------\n";

	queue<pair<int, int> > Q;

	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (arr[i][j] == 0) {
				cnt++;
				arr[i][j] = 1;
				int this_area = 1;
				Q.push(make_pair(i, j));

				while (!Q.empty()) {
					int cur_x = Q.front().first;
					int cur_y = Q.front().second;
					Q.pop();

					for (int k = 0; k < 4; k++) {
						int nx = cur_x + dx[k];
						int ny = cur_y + dy[k];
						if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
						if (arr[nx][ny] == 0) {
							arr[nx][ny] = ++this_area;
							Q.push({ nx,ny });
						}
					}
				}
				ans.push_back(this_area);
			}
		}
	}


	//결과 확인
	//for (int i = 0; i < m; i++) {
	//	for (int j = 0; j < n; j++) {
	//		cout << arr[i][j] << ' ';
	//	}
	//	cout << '\n';
	//}
	//cout << "-------------------\n";


	//정답 출력
	cout << cnt << '\n';
	sort(ans.begin(), ans.end());
	for (int i = 0; i < ans.size(); i++) {
		cout << ans[i] << ' ';
	}

}

백준 2583 시간, 메모리

일반적인 BFS탐색 문제와 비슷하다.

 

다만 좌표설정하는 부분을 잘 유의해야할 필요가 있다.

 

 

반응형
반응형
#include <bits/stdc++.h>
using namespace std;

struct Node{
	int row, col;
	Node(int a, int b){
		row=a;
		col=b;
	}
	
};

int arr[7][7];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};

int main(){
	//freopen("input.txt.txt","rt",stdin);
	ios::sync_with_stdio(false);
	cin.tie(0);
	queue<Node> Q;

	for(int i=0; i<7; i++){
		for(int j=0; j<7; j++){
			scanf("%d",&arr[i][j]);
			if(arr[i][j]==1) arr[i][j] = -1;
		}
	}
	arr[0][0] = 1;
	Q.push(Node(0,0));
	while(!Q.empty()){
		int x = Q.front().row;
		int y = Q.front().col;
		Q.pop();
		
		if(x==6 && y==6) break;
		
		
		for(int i=0; i<4; i++){
			int nx = x+dx[i];
			int ny = y+dy[i];
			
			if(nx<0||nx>6||ny<0||ny>6) continue;
			if(arr[nx][ny]==-1 || arr[nx][ny]>0) continue;
			
			arr[nx][ny] = arr[x][y]+1;
			Q.push(Node(nx,ny));
		}
	}
	
	printf("%d",arr[6][6]-1);
}

장애물을 -1로 두고

 

거리를 양수로 표기하면서 BFS를 돌면 편하다.

 

첫 시작점도 방문했다는걸 표기하기 위해 1로 둔다.

 

나중에 답을 구할 땐 1을 다시 빼준다.

반응형

+ Recent posts