12100번 2048(Easy)

문제

2048 게임은 4×4 크기의 보드에서 혼자 즐기는 재미있는 게임이다. 이 링크를 누르면 게임을 해볼 수 있다.

이 게임에서 한 번의 이동은 보드 위에 있는 전체 블록을 상하좌우 네 방향 중 하나로 이동시키는 것이다. 이때, 같은 값을 갖는 두 블록이 충돌하면 두 블록은 하나로 합쳐지게 된다. 한 번의 이동에서 이미 합쳐진 블록은 또 다른 블록과 다시 합쳐질 수 없다. (실제 게임에서는 이동을 한 번 할 때마다 블록이 추가되지만, 이 문제에서 블록이 추가되는 경우는 없다)

 

<그림 1> <그림 2> <그림 3>

<그림 1>의 경우에서 위로 블록을 이동시키면 <그림 2>의 상태가 된다. 여기서, 왼쪽으로 블록을 이동시키면 <그림 3>의 상태가 된다.

 

<그림 4> <그림 5> <그림 6> <그림 7>

<그림 4>의 상태에서 블록을 오른쪽으로 이동시키면 <그림 5>가 되고, 여기서 다시 위로 블록을 이동시키면 <그림 6>이 된다. 여기서 오른쪽으로 블록을 이동시켜 <그림 7>을 만들 수 있다.

 

<그림 8> <그림 9>

<그림 8>의 상태에서 왼쪽으로 블록을 옮기면 어떻게 될까? 2가 충돌하기 때문에, 4로 합쳐지게 되고 <그림 9>의 상태가 된다.

 

<그림 10> <그림 11> <그림 12> <그림 13>

<그림 10>에서 위로 블록을 이동시키면 <그림 11>의 상태가 된다. 

<그림 12>의 경우에 위로 블록을 이동시키면 <그림 13>의 상태가 되는데, 그 이유는 한 번의 이동에서 이미 합쳐진 블록은 또 합쳐질 수 없기 때문이다.

 

<그림 14> <그림 15>

마지막으로, 똑같은 수가 세 개가 있는 경우에는 이동하려고 하는 쪽의 칸이 먼저 합쳐진다. 예를 들어, 위로 이동시키는 경우에는 위쪽에 있는 블록이 먼저 합쳐지게 된다. <그림 14>의 경우에 위로 이동하면 <그림 15>를 만든다.

이 문제에서 다루는 2048 게임은 보드의 크기가 N×N 이다. 보드의 크기와 보드판의 블록 상태가 주어졌을 때, 최대 5번 이동해서 만들 수 있는 가장 큰 블록의 값을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.

 

출력

최대 5번 이동시켜서 얻을 수 있는 가장 큰 블록을 출력한다.

 

풀이과정

1. 상, 하, 좌, 우의 모든 조합을 DFS을 통하여 만든다.

2. 조합의 방향에 맞추어 블록을 움직인다.

3. 이웃한 값이 서로 같다면 더해준다.

4. 합해진 곳의 공백을 없애기 위해 다시 한번 방향을 맞추어 블록을 움직인다.

5. 2~4를 최대5번 반복한다.

6. 5번 이후 맵에 남아있는 숫자를 더한 후 이전 결과 값보다 크다면 결과를 갱신한다.

7. 출력

 

소스코드

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
int map[20][20];
int cMap[20][20];
int mapSize;
int ans=0;
vector<int> command;

void input(){
	cin >> mapSize;
	for (int i = 0; i < mapSize; ++i)
		for (int j = 0; j < mapSize; ++j)
			cin >> map[i][j];
}

//맵 복사
void copy(){
	for (int i = 0; i < mapSize; ++i)
		for (int j = 0; j < mapSize; ++j)
			cMap[i][j]=map[i][j];
}

// 움직이기
// 상하좌우방향에 맞추어 맵에서 0인 아닌 값을  Queue에 넣는다.
// 해당 맵의 위치는 0으로 바꾼다.
// Queue에 값을 모두 넣었다면 상하좌우 방향에 맞추어 Queue에 있는 값을 순서대로 넣는다.
void move(int dir){
	if(dir==0){//상
		for (int j = 0; j < mapSize; ++j)
		{
			queue<int> q;
			for (int i = 0; i < mapSize; ++i)
			{
				if(cMap[i][j]!=0){
					q.push(cMap[i][j]);
					cMap[i][j]=0;
				}
			}
			int size=q.size();
			for (int i = 0; i < size; ++i)
			{
				cMap[i][j]=q.front();
				q.pop();
			}
		}
	}
	else if(dir==1){//우
		for (int i = 0; i < mapSize; ++i)
		{
			queue<int> q;
			for (int j = mapSize-1; j >= 0; j--)
			{
				if(cMap[i][j]!=0){
					q.push(cMap[i][j]);
					cMap[i][j]=0;
				}
			}
			int size=q.size();
			for (int j = mapSize-1; j >= mapSize-size; j--)
			{
				cMap[i][j]=q.front();
				q.pop();
			}
		}

	}
	else if(dir==2){//하
		for (int j = 0; j < mapSize; ++j)
		{
			queue<int> q;
			for (int i = mapSize-1; i >= 0; i--)
			{
				if(cMap[i][j]!=0){
					q.push(cMap[i][j]);
					cMap[i][j]=0;
				}
			}
			int size=q.size();
			for (int i = mapSize-1; i >= mapSize-size; i--)
			{
				cMap[i][j]=q.front();
				q.pop();
			}
		}
		
	}
	else if(dir==3){//좌 
		for (int i = 0; i < mapSize; ++i)
		{
			queue<int> q;
			for (int j = 0; j < mapSize; j++)
			{
				if(cMap[i][j]!=0){
					q.push(cMap[i][j]);
					cMap[i][j]=0;
				}
			}
			int size=q.size();
			for (int j = 0; j < size; j++)
			{
				cMap[i][j]=q.front();
				q.pop();
			}
		}
		
	}
}

// 이웃한 값의 숫자가 같다면 순서가 빠른 위치를 2배하고 느린 위치를 0으로 바꾼다.
void sumNum(int dir){
	if(dir==0){// 상
		for (int j = 0; j < mapSize; ++j)
		{
			for (int i = 0; i < mapSize-2; ++i)
			{
				if( cMap[i][j]!=0 && (cMap[i+1][j] == cMap[i][j]) ){
					cMap[i][j]*=2;
					cMap[i+1][j]=0;
				}
			}
		}
	}
	else if(dir==1){// 우 
		for (int i = 0; i < mapSize; ++i)
		{
			for (int j = mapSize-1; j >= 1; j--)
			{
				if( cMap[i][j]!=0 && (cMap[i][j-1] == cMap[i][j]) ){
					cMap[i][j]*=2;
					cMap[i][j-1]=0;
				}
			}
		}

	}
	else if(dir==2){//하
		for (int j = 0; j < mapSize; ++j)
		{
			for (int i = mapSize-1; i >= 1; i--)
			{
				if( cMap[i][j]!=0 && (cMap[i-1][j] == cMap[i][j]) ){
					cMap[i][j]*=2;
					cMap[i-1][j]=0;
				}
			}
		}
		
	}
	else if(dir==3){//좌
		for (int i = 0; i < mapSize; ++i)
		{
			for (int j = 0; j < mapSize-2; ++j)
			{
				if( cMap[i][j]!=0 && (cMap[i][j+1] == cMap[i][j]) ){
					cMap[i][j]*=2;
					cMap[i][j+1]=0;
				}
			}
		}
		
	}

}

void solve(){
	memset(cMap,0,sizeof(cMap));
	copy(); // 임시 맵 복사
	for (int i = 0; i < 5; ++i)
	{
		move(command[i]);//한 방향으로 움직인다.
		sumNum(command[i]);//합친다
		move(command[i]);//합친 후 공백을 없애기 위해 다시 움직인다. 
	}
	int result=0;
	// 합 계산
	for (int i = 0; i < mapSize; ++i)
		for (int j = 0; j < mapSize; ++j)
			if(cMap[i][j]>result)
				result=cMap[i][j];

	if(ans<result)
		ans=result;


}

// 명령의 조합 만들기
void dfs(){
	if(command.size()==5){
		solve();
		return;
	}

	for (int i = 0; i < 4; ++i)
	{
		command.push_back(i);
		dfs();
		command.pop_back();
	}

}

int main(){
	input();
	dfs();
	cout << ans;

}

 

문제, 사진 출처

백준 : https://www.acmicpc.net/problem/12100

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

 

16236아기 상어

 

문제

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다.

아기 상어와 물고기는 모두 크기를 가지고 있고, 이 크기는 자연수이다. 가장 처음에 아기 상어의 크기는 2이고, 아기 상어는 1초에 상하좌우로 인접한 한 칸씩 이동한다.

아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고, 나머지 칸은 모두 지나갈 수 있다. 아기 상어는 자신의 크기보다 작은 물고기만 먹을 수 있다. 따라서, 크기가 같은 물고기는 먹을 수 없지만, 그 물고기가 있는 칸은 지나갈 수 있다.

아기 상어가 어디로 이동할지 결정하는 방법은 아래와 같다.

  • 더 이상 먹을 수 있는 물고기가 공간에 없다면 아기 상어는 엄마 상어에게 도움을 요청한다.
  • 먹을 수 있는 물고기가 1마리라면, 그 물고기를 먹으러 간다.
  • 먹을 수 있는 물고기가 1마리보다 많다면, 거리가 가장 가까운 물고기를 먹으러 간다.
    • 거리는 아기 상어가 있는 칸에서 물고기가 있는 칸으로 이동할 때, 지나야하는 칸의 개수의 최솟값이다.
    • 거리가 가까운 물고기가 많다면, 가장 위에 있는 물고기, 그러한 물고기가 여러마리라면, 가장 왼쪽에 있는 물고기를 먹는다.

아기 상어의 이동은 1초 걸리고, 물고기를 먹는데 걸리는 시간은 없다고 가정한다. 즉, 아기 상어가 먹을 수 있는 물고기가 있는 칸으로 이동했다면, 이동과 동시에 물고기를 먹는다. 물고기를 먹으면, 그 칸은 빈 칸이 된다.

아기 상어는 자신의 크기와 같은 수의 물고기를 먹을 때 마다 크기가 1 증가한다. 예를 들어, 크기가 2인 아기 상어는 물고기를 2마리 먹으면 크기가 3이 된다.

공간의 상태가 주어졌을 때, 아기 상어가 몇 초 동안 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는지 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 공간의 크기 N(2 ≤ N ≤ 20)이 주어진다.

둘째 줄부터 N개의 줄에 공간의 상태가 주어진다. 공간의 상태는 0, 1, 2, 3, 4, 5, 6, 9로 이루어져 있고, 아래와 같은 의미를 가진다.

  • 0: 빈 칸
  • 1, 2, 3, 4, 5, 6: 칸에 있는 물고기의 크기
  • 9: 아기 상어의 위치

아기 상어는 공간에 한 마리 있다.

 

출력

첫째 줄에 아기 상어가 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는 시간을 출력한다.

 

 

풀이과정

1. 아기 상어의 위치를 기준으로 거리의 길이 단위로 먹을 수 있거나 이동할 수 있는 경로의 위치를 큐에 추가한다.

 

2 - 1 먹을 수 있는 물고기가 있다면 해당 물고기를 주어진 우선순위(상 좌 우 하)에 위치한 물고기를 먹고 해당 위치에서 다시 물고기를 찾는다.

 

2 - 2 먹을 수 있는 물고기가 없지만 이동할 수 있는 경로가 있다면 경로의 위치를 큐에 추가한다.

 

2 - 3 물고기도 없고 이동할 수 있는 경로도 없다면 함수를 끝낸다.

 

 

코드

#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;


struct Shark
{
	int y;//좌표
	int x;
	int size;//크기
	int hungry;//먹은 수(사이즈 만큼먹으면 초기화)
	int cnt;//시간초카운트
};

Shark shark;
int map[20][20];
int N;
int dy[]={0,0,1,-1};
int dx[]={1,-1,0,0};


void input(){
	cin >> N;
	for (int i = 0; i < N; ++i)
		for (int j = 0; j < N; ++j){
			cin >> map[i][j];
			if(map[i][j]==9){
				shark.y=i;
				shark.x=j;
				shark.size=2;
				shark.hungry=0;
				shark.cnt=0;
				map[i][j]=0;
			}
		}
}

// 먹기
void eat(Shark temp , int cnt){
	shark.y=temp.y;
	shark.x=temp.x;
	if(shark.hungry+1==shark.size){//사이즈만큼 먹으면 크기증가
		shark.size++;
		shark.hungry=0;
	}
	else
		shark.hungry++;
	shark.cnt+=cnt;
	map[temp.y][temp.x]=0;

}

// 먹을 수 있는 물고기  찾기
bool findFood(){
	queue<Shark> q;
	q.push(shark);
	bool visit[N][N];
	memset(visit,false,sizeof(visit));
	visit[shark.y][shark.x]=true;
	int count=0;
	while(!q.empty()){
		int size=q.size();
		vector<Shark> food;
		for (int k = 0; k < size; ++k)
		{	
			Shark temp;
			temp=q.front();
			q.pop();
			for (int i = 0; i < 4; ++i){
				int ty=dy[i]+temp.y;
				int tx=dx[i]+temp.x;
				if(visit[ty][tx])
					continue;
				if(ty<0||tx<0||tx>=N||ty>=N)
					continue;
				if(map[ty][tx]>shark.size)
					continue;

				Shark tShark=temp;
				tShark.y=ty;
				tShark.x=tx;
				
				//먹을 수 있는 물고기 중 문제에서 주어진 우선 순위로 한 마리의 물고기만 저장
				if(map[ty][tx]<shark.size && map[ty][tx]>0){
					visit[ty][tx]=true;
					if(food.size()>0){//이미 먹을 수 있는 물고기가 있는 경우
						if(food[0].y>tShark.y){// 위 우선
							food.pop_back();
							food.push_back(tShark);
						}
						else if(food[0].y==tShark.y){// 좌측 우선  
							if(food[0].x>tShark.x){
								food.pop_back();
								food.push_back(tShark);
							}
						}
					}
					else// 먹을 수 있는 물고기가 비어있으면 바로 추가
						food.push_back(tShark);
				}
				else{
					visit[ty][tx]=true;
					q.push(tShark);
				}
			}
		}
		count++;
		// 먹을 수 있는 상어가 있으면 먹고 찾기를 그만 둠 
		if(food.size()>0){
			eat(food[0],count);
			return true;
		}

	}
	return false;


}

void solve(){
	// 먹을 수 있는 상어가 없을 경우 끝낸다.
	while(1){
		if(findFood()){

		}
		else
			break;
	}
}

int main(){
	input();
	solve();
	cout << shark.cnt;

	
}

 

문제 출처

백준  https://www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가��

www.acmicpc.net

 

14888번 연산자 끼워넣기

문제

N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)으로만 이루어져 있다.

우리는 수와 수 사이에 연산자를 하나씩 넣어서, 수식을 하나 만들 수 있다. 이때, 주어진 수의 순서를 바꾸면 안 된다.

예를 들어, 6개의 수로 이루어진 수열이 1, 2, 3, 4, 5, 6이고, 주어진 연산자가 덧셈(+) 2개, 뺄셈(-) 1개, 곱셈(×) 1개, 나눗셈(÷) 1개인 경우에는 총 60가지의 식을 만들 수 있다. 예를 들어, 아래와 같은 식을 만들 수 있다.

  • 1+2+3-4×5÷6
  • 1÷2+3+4-5×6
  • 1+2÷3×4-5+6
  • 1÷2×3-4+5+6

식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 진행해야 한다. 또, 나눗셈은 정수 나눗셈으로 몫만 취한다. 음수를 양수로 나눌 때는 C++14의 기준을 따른다. 즉, 양수로 바꾼 뒤 몫을 취하고, 그 몫을 음수로 바꾼 것과 같다. 이에 따라서, 위의 식 4개의 결과를 계산해보면 아래와 같다.

  • 1+2+3-4×5÷6 = 1
  • 1÷2+3+4-5×6 = 12
  • 1+2÷3×4-5+6 = 5
  • 1÷2×3-4+5+6 = 7

N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과가 최대인 것과 최소인 것을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 곱셈(×)의 개수, 나눗셈(÷)의 개수이다. 

 

출력

첫째 줄에 만들 수 있는 식의 결과의 최댓값을, 둘째 줄에는 최솟값을 출력한다. 연산자를 어떻게 끼워넣어도 항상 -10억보다 크거나 같고, 10억보다 작거나 같은 결과가 나오는 입력만 주어진다. 또한, 앞에서부터 계산했을 때, 중간에 계산되는 식의 결과도 항상 -10억보다 크거나 같고, 10억보다 작거나 같다.

 

 

풀이 접근

1. 입력받은 연산자들을 배열로 반듬 ex) ++---+*/

2. 재귀를 통하여 모든 조합을 만듬

3. 만들어진 조합을 통하여 연산 후 최대 최소를 갱신

 

코드

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
int n;
int num[11];
int calculate[4];
bool check[10];
int maxAns=-1000000000; // 최대 결과
int minAns=1000000000; //최소 결과
vector<int> calV; // +(0) -(1) *(2) /(3) 조합을 만들기 위해 만든 벡터 
vector<int> start; // dfs() 함수에 시작 할때 넣을 빈 벡터 

void input(){
	cin >> n;
	for(int i=0; i < n; i++)
		cin >> num[i];
	for(int i=0; i < 4; i++){
		cin >> calculate[i];
		for(int j=0; j<calculate[i]; j++){
			calV.push_back(i);
		}
	}
	memset(check,false,sizeof(check));
}


void solve(vector<int> v){
	int tempResult=num[0];
	for(int i=0; i<v.size(); i++){
		if(v[i]==0){
			tempResult+=num[i+1];
		}
		else if(v[i]==1){
			tempResult-=num[i+1];
		}
		else if(v[i]==2){
			tempResult*=num[i+1];
		}
		else{
			tempResult/=num[i+1];
		}
	}
	if(tempResult>maxAns)
		maxAns=tempResult;
	if(tempResult<minAns)
		minAns=tempResult;
	
}

// 조합 만들기
void dfs(vector<int> v){
	
	if(v.size()==n-1){
		solve(v);
		return;
	}

	for(int i=0; i<calV.size(); i++){
		if(check[i])
			continue;
		check[i]=true;
		v.push_back(calV[i]);
		dfs(v);
		v.pop_back();
		check[i]=false;
	}
	
}




int main(){
	input();
	dfs(start);
	cout << maxAns << "\n" << minAns;
}

 

문제 출처

백준 https://www.acmicpc.net/problem/14888

 

14888번: 연산자 끼워넣기

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, ��

www.acmicpc.net

 

15683번 감시

문제

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감시할 수 있는 방법은 다음과 같다.

1번 2번 3번 4번 5번

1번 CCTV는 한 쪽 방향만 감시할 수 있다. 2번과 3번은 두 방향을 감시할 수 있는데, 2번은 감시하는 방향이 서로 반대방향이어야 하고, 3번은 직각 방향이어야 한다. 4번은 세 방향, 5번은 네 방향을 감시할 수 있다.

CCTV는 감시할 수 있는 방향에 있는 칸 전체를 감시할 수 있다. 사무실에는 벽이 있는데, CCTV는 벽을 통과할 수 없다. CCTV가 감시할 수 없는 영역은 사각지대라고 한다.

CCTV는 회전시킬 수 있는데, 회전은 항상 90도 방향으로 해야 하며, 감시하려고 하는 방향이 가로 또는 세로 방향이어야 한다.

 

 

지도에서 0은 빈 칸, 6은 벽, 1~5는 CCTV의 번호이다. 위의 예시에서 1번의 방향에 따라 감시할 수 있는 영역을 '#'로 나타내면 아래와 같다.

 

 

CCTV는 벽을 통과할 수 없기 때문에, 1번이 → 방향을 감시하고 있을 때는 6의 오른쪽에 있는 벽을 감시할 수 없다.

 

위의 예시에서 감시할 수 있는 방향을 알아보면 아래와 같다.

왼쪽 상단 2: ↔, 오른쪽 하단 2: ↔ 왼쪽 상단 2: ↔, 오른쪽 하단 2: ↕ 왼쪽 상단 2: ↕, 오른쪽 하단 2: ↔ 왼쪽 상단 2: ↕, 오른쪽 하단 2: ↕

 

CCTV는 CCTV를 통과할 수 있다. 아래 예시를 보자.

 

위와 같은 경우에 2의 방향이 ↕ 3의 방향이 ←와 ↓인 경우 감시받는 영역은 다음과 같다.

 

 

사무실의 크기와 상태, 그리고 CCTV의 정보가 주어졌을 때, CCTV의 방향을 적절히 정해서, 사각 지대의 최소 크기를 구하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에 사무실의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 8)

둘째 줄부터 N개의 줄에는 사무실 각 칸의 정보가 주어진다. 0은 빈 칸, 6은 벽, 1~5는 CCTV를 나타내고, 문제에서 설명한 CCTV의 종류이다. 

CCTV의 최대 개수는 8개를 넘지 않는다.

출력

첫째 줄에 사각 지대의 최소 크기를 출력한다.

 

코드

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int row,col;
int map[8][8];
int cMap[8][8]; // 임시맵 

struct cctv
{
	int cctvNum; // cctv 번호 
	int y; // 좌표 
	int x; // 좌표 
	int dir; // 방향
};

int result=64;
vector<cctv> cctvInfo;


void input(){
	memset(map,0,sizeof(map));
	cin >> col >> row;
	for (int i = 0; i < col; ++i)
		for (int j = 0; j < row; ++j){
			cin >> map[i][j];
			if(map[i][j]!=0&&map[i][j]!=6){
				cctvInfo.push_back({map[i][j],i,j,0});
			}
		}
}

void cpyMap(){
	for (int i = 0; i < col; ++i)
		for (int j = 0; j < row; ++j)
			cMap[i][j]=map[i][j];
	
}

void fill(int index, cctv c){
	// 위로 쭉 채우기 
	if(index==0){
		for (int i = c.y; i >= 0; i--)
		{
			if(cMap[i][c.x]==6)
				break;
			if(cMap[i][c.x]==0)
				cMap[i][c.x]=-1;
		}
	}// 오른쪽 쭉 채우기 
	else if(index==1){
		for (int i = c.x; i < row; ++i)
		{
			if(cMap[c.y][i]==6)
				break;
			if(cMap[c.y][i]==0)
				cMap[c.y][i]=-1;
		}

	}// 아래 쭉 채우기 
	else if(index==2){
		for (int i = c.y; i < col; i++)
		{
			if(cMap[i][c.x]==6)
				break;
			if(cMap[i][c.x]==0)
				cMap[i][c.x]=-1;
		}
		
	}// 왼쪽 쭉 채우기 
	else if(index==3){
		for (int i = c.x; i >=0; i--)
		{
			if(cMap[c.y][i]==6)
				break;
			if(cMap[c.y][i]==0)
				cMap[c.y][i]=-1;
		}
		
	}


}


void search(){
	int count=0;
	for (int i = 0; i < cctvInfo.size(); ++i)
	{
		// 1번 카메라
		if(cctvInfo[i].cctvNum==1){
			fill(cctvInfo[i].dir,cctvInfo[i]);
		}//2번 카메라 
		else if(cctvInfo[i].cctvNum==2){
			if(cctvInfo[i].dir%2==0){
				fill(0,cctvInfo[i]);
				fill(2,cctvInfo[i]);
			}
			else{
				fill(1,cctvInfo[i]);
				fill(3,cctvInfo[i]);
			}
		}// 3번 카메라 
		else if(cctvInfo[i].cctvNum==3){
			if(cctvInfo[i].dir==3){
				fill(0,cctvInfo[i]);
				fill(3,cctvInfo[i]);
			}
			else{
				fill(cctvInfo[i].dir,cctvInfo[i]);
				fill(cctvInfo[i].dir+1,cctvInfo[i]);
			}
		}// 4번카메라 
		else if(cctvInfo[i].cctvNum==4){
			for(int j=0; j<4; j++){
				if(j==cctvInfo[i].dir)
					continue;
				fill(j,cctvInfo[i]);
			}
			
		}// 5번 카메라 
		else{
			fill(0,cctvInfo[i]);
			fill(1,cctvInfo[i]);
			fill(2,cctvInfo[i]);
			fill(3,cctvInfo[i]);
		}

	}

	// 사각지대 구하기
	for (int i = 0; i < col; ++i)
		for (int j = 0; j < row; ++j)
			if(cMap[i][j]==0) count++;


	// 결과값  구하기
	if(result>count)
		result=count;
		
			

}


//방향의 조합을 만들기
void dfs(int index){
	if(index==cctvInfo.size()){
		cpyMap();//임시 맵 만들기
		search();//감시 사각지대 찾기
		return;
	}

	for(int i=0; i<4; i++){
		cctvInfo[index].dir=i;
		dfs(index+1);
	}

}



int main(){
	input();
	dfs(0);
	cout << result;

	
}

 

문제출처

백준 https://www.acmicpc.net/problem/15683

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감��

www.acmicpc.net

삼성 SW 역량 테스트 기출 문제

3190번 뱀

문제

'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다.

게임은 NxN 정사각 보드위에서 진행되고, 몇몇 칸에는 사과가 놓여져 있다. 보드의 상하좌우 끝에 벽이 있다. 게임이 시작할때 뱀은 맨위 맨좌측에 위치하고 뱀의 길이는 1 이다. 뱀은 처음에 오른쪽을 향한다.

뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따른다.

  • 먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다.
  • 만약 이동한 칸에 사과가 있다면, 그 칸에 있던 사과가 없어지고 꼬리는 움직이지 않는다.
  • 만약 이동한 칸에 사과가 없다면, 몸길이를 줄여서 꼬리가 위치한 칸을 비워준다. 즉, 몸길이는 변하지 않는다.

사과의 위치와 뱀의 이동경로가 주어질 때 이 게임이 몇 초에 끝나는지 계산하라.

 

입력

첫째 줄에 보드의 크기 N이 주어진다. (2 ≤ N ≤ 100) 다음 줄에 사과의 개수 K가 주어진다. (0 ≤ K ≤ 100)

다음 K개의 줄에는 사과의 위치가 주어지는데, 첫 번째 정수는 행, 두 번째 정수는 열 위치를 의미한다. 사과의 위치는 모두 다르며, 맨 위 맨 좌측 (1행 1열) 에는 사과가 없다.

다음 줄에는 뱀의 방향 변환 횟수 L 이 주어진다. (1 ≤ L ≤ 100)

다음 L개의 줄에는 뱀의 방향 변환 정보가 주어지는데, 정수 X와 문자 C로 이루어져 있으며. 게임 시작 시간으로부터 X초가 끝난 뒤에 왼쪽(C가 'L') 또는 오른쪽(C가 'D')로 90도 방향을 회전시킨다는 뜻이다. X는 10,000 이하의 양의 정수이며, 방향 전환 정보는 X가 증가하는 순으로 주어진다.

 

출력

첫째 줄에 게임이 몇 초에 끝나는지 출력한다.

 

 

코드

#include <iostream>
#include <cstring>
#include <vector>
#include <deque>
using namespace std;
int board[101][101];// 보드 
int boardSize;// 보드 사이즈 
int apple; // 사과 수 
int command; // 뱀 방향 변환 정보
int cnt=0; // 카운트
int snakeDir=1; // 뱀 방향
int dx[]={0,1,0,-1}; // 상 우 하 좌 
int dy[]={-1,0,1,0};

deque<pair<int,int>> snake; // 뱀의 몸통 
vector<pair<int,char>> snakeMove; // 뱀이 움직이는 정보 <시간 , 방향 >


void input(){

	cin >> boardSize;
	cin >> apple;
	for (int i = 0; i < apple; ++i)
	{
		int y,x;
		cin >> y >> x;
		board[y][x]=1;
	}
	cin >> command;
	int temp=0;
	for (int i = 0; i < command; ++i)
	{
		int time;
		char dir;
		cin>> time >> dir;
		temp=time-temp;
		snakeMove.push_back({temp,dir});
		temp=time;
	}

	// 마지막 명령어 후에는 한방향으로 쭉 움직임
	snakeMove.push_back({1000,'D'});
}


void move(){
	//시작
	snake.push_back({1,1});
	board[1][1]=2;

	for (int i = 0; i <= command; ++i)
	{
		pair<int,char> temp=snakeMove[i];
		bool check=false;
		for (int j = 0; j < temp.first; j++)
		{
			int tx=snake.back().second+dx[snakeDir];
			int ty=snake.back().first+dy[snakeDir];
			// 맵을 벗어나거나  자신의 몸통에 부서지면 종료 
			if(ty<=0||tx<=0||tx>boardSize||ty>boardSize||board[ty][tx]==2){
				check=true;
				break;
			}
			// 가는곳이 사과일때 길이만 증가
			if(board[ty][tx]==1){
				snake.push_back({ty,tx});
				board[ty][tx]=2;
			}// 가는곳에 사과없을때 꽁무니는 줄어든다.
			else if(board[ty][tx]==0){
				snake.push_back({ty,tx});
				board[ty][tx]=2;
				board[snake.front().first][snake.front().second]=0;
				snake.pop_front();

			}

			cnt++;

		}
		if(check)
			break;
		// 방향 전환 
		if(temp.second=='L'){
			if(snakeDir==0)
				snakeDir=4;
			snakeDir--;
		}
		else if(temp.second=='D'){
			if(snakeDir==3)
				snakeDir=-1;
			snakeDir++;
		}

	}

}


int main(){
	memset(board,0,sizeof(board));
	input();
	move();
	cout << cnt+1;
	
}

문제출처

백준 https://www.acmicpc.net/problem/3190

 

3190번: 뱀

문제  'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다.

www.acmicpc.net

 

13458 시험 감독

문제

총 N개의 시험장이 있고, 각각의 시험장마다 응시자들이 있다. i번 시험장에 있는 응시자의 수는 Ai명이다.

감독관은 총감독관과 부감독관으로 두 종류가 있다. 총감독관은 한 시험장에서 감시할 수 있는 응시자의 수가 B명이고, 부감독관은 한 시험장에서 감시할 수 있는 응시자의 수가 C명이다.

각각의 시험장에 총감독관은 오직 1명만 있어야 하고, 부감독관은 여러 명 있어도 된다.

각 시험장마다 응시생들을 모두 감시해야 한다. 이때, 필요한 감독관 수의 최솟값을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 시험장의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

둘째 줄에는 각 시험장에 있는 응시자의 수 Ai (1 ≤ Ai ≤ 1,000,000)가 주어진다.

셋째 줄에는 B와 C가 주어진다. (1 ≤ B, C ≤ 1,000,000)

 

출력

각 시험장마다 응시생을 모두 감독하기 위해 필요한 감독관의 최소 수를 출력한다.

 

 

 


코드

#include <iostream>
using namespace std;


int testSite[1000000]; // 시험장
int n; // 시험장 개수
int SuperMan; // 총감독 감시가능 숫자
int SubMan; // 부감독 감시가능 숫자 
long long result=0;

void input(){
	cin >> n;
	for (int i = 0; i < n; ++i)
	{
		cin >> testSite[i];
	}
	cin >> SuperMan >> SubMan;
}


int main(){
	
	input();

	// 시험장에 총감독은 항상 1명
	result+=n;

	for (int i = 0; i < n; ++i)
	{
		int temp; 
		int tempRsult;

		// 총감독 감시수 빼기
		temp=testSite[i]-SuperMan;

		if(temp<=0){//총감독 혼자 가능 
			continue;
		}
		else if(temp%SubMan==0){//부감독 감시자수까지 해서 딱 떨어졌을때 
			tempRsult=temp/SubMan;
		}
		else{// 딱 떨어지지 않았을때
			tempRsult=temp/SubMan+1;
		}
		result+=tempRsult;
	}
	cout<<result;

}

 

 

문제 출처

백준 https://www.acmicpc.net/problem/13458

 

13458번: 시험 감독

첫째 줄에 시험장의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 각 시험장에 있는 응시자의 수 Ai (1 ≤ Ai ≤ 1,000,000)가 주어진다. 셋째 줄에는 B와 C가 주어진다. (1 ≤ B, C ≤ 1,000,000)

www.acmicpc.net

 

+ Recent posts