반응형

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

 

[문제풀이]

1.BFS로 풀수 있다. 

2.L:육지로 이동가능한곳, W:물로 이동할 수 없다 

3.L만 찾아서 1개씩 큐에 저장후 이동할 수 있는 가장 먼 거리를 찾는 문제이다.

4.map정보가 같은 크기의 visited배열을 만들어서 방문 기록을 하고 매번 초기화 해줘야한다.

 

#include <iostream>
#include <queue>
#include <memory.h>
using namespace std;
#define MAXN (50)
int N, M;//세로, 가로
char map[MAXN+10][MAXN+10];//지도정보
int visited[MAXN+10][MAXN+10];//방문 표시 
struct Q{
	int y,x,t;
};
int count=0,ans=-1;
int BFS(int y, int x,int t){
	queue<Q>q;
	int dy[]={-1,1,0,0};//동서남북
	int dx[]={0,0,-1,1};
	//1.초기화 
	count=0;
	q={};
	//2.큐에 초기값 저장 
	q.push({y,x,t});	
	//3.반복문 
	while(!q.empty()){
		Q cur=q.front();q.pop();
		visited[y][x]=1;

		for(int i=0; i<4; i++){
			t=cur.t;
			int ny=cur.y+dy[i];
			int nx=cur.x+dx[i];
			if((ny<0) || (ny>=N) || (nx<0) || (nx>=M) || map[ny][nx]!='L') continue;
			if(visited[ny][nx]==0){
				visited[ny][nx]=1;
				q.push({ny,nx,t+1});
				count=t+1;
				if(ans<count) ans=count;//ans에 최대값 업데이트 
			}
		}
	}
	return ans;
}
void Solve(){
	for (int i=0; i<N; i++){
		for (int j=0; j<M; j++){
			if(map[i][j]=='L'){
				ans=BFS(i,j,0);
				memset(visited,false,sizeof(visited));
			}
		}
	}
	cout<<ans<<endl;
}
void InputData(){
	cin>>N>>M;
	for (int i=0; i<N; i++){
		cin>>map[i];
	}
}
int main(){
	InputData();
	Solve();
	return 0;
}
반응형

'Algorithm > BFS,DFS' 카테고리의 다른 글

[c++][백준]뱀과 사다리  (0) 2022.05.16
[C++][백준]1520 내리막길  (0) 2022.04.10
[C++][백준]14502 연구소  (0) 2022.04.10
[C++][백준]적록색약  (0) 2022.04.10
[c++][algoritm][baekjoon]7562 나이트의 이동  (0) 2021.09.23
반응형

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

 

1520번: 내리막 길

첫째 줄에는 지도의 세로의 크기 M과 가로의 크기 N이 빈칸을 사이에 두고 주어진다. 이어 다음 M개 줄에 걸쳐 한 줄에 N개씩 위에서부터 차례로 각 지점의 높이가 빈 칸을 사이에 두고 주어진다.

www.acmicpc.net

 

[문제풀이]

1.dfs를 이용해서 푸는 문제이다.

2.최종 출력값은 visited[0][0]=3이 정답인데, visited[N-1][M-1]의 값이 정답으로 생각했는데, 의외인것 같다.

입력과 좌표에 따른 visited값

/*1520 내리막길 */
#include<iostream>
#include<memory.h>
using namespace std;

#define MAXN (int)5e2+10
int M,N;//행,열 
int map[MAXN][MAXN];
int visited[MAXN][MAXN]={0,};//방문 표시
int dy[]={-1,1,0,0};//상하좌우
int dx[]={0,0,-1,1};
bool isInside(int a, int b){
	return ( (a>=0) && (a<M) && (b>=0) && (b<N));
}
int DFS(int y, int x){
	if(y==M-1 && x==N-1) return 1;
	if(visited[y][x]!=-1) return visited[y][x];
	visited[y][x]=0;
	for(int i=0; i<4; i++){
		int ny=y+dy[i];
		int nx=x+dx[i];
		if(isInside(ny,nx)){
			if(map[ny][nx]<map[y][x])
				visited[y][x]+=DFS(ny,nx);
		}
	}
	return visited[y][x];
}
void InputData(){
	cin>>M>>N;
	for(int i=0; i<M; i++){
		for(int j=0; j<N; j++){
			cin>>map[i][j];
		}
	}
	memset(visited,-1,sizeof(visited));
}
int main(){
	InputData();
	cout<<DFS(0,0);
	return 0;
}
반응형

'Algorithm > BFS,DFS' 카테고리의 다른 글

[c++][백준]뱀과 사다리  (0) 2022.05.16
[C++][BFS]백준 2589 보물섬  (0) 2022.04.11
[C++][백준]14502 연구소  (0) 2022.04.10
[C++][백준]적록색약  (0) 2022.04.10
[c++][algoritm][baekjoon]7562 나이트의 이동  (0) 2021.09.23
반응형

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

 

[풀이과정]

1.바이러스 걸린 방의 위치 저장 해 둔다, 여기서는 vector를 사용했다.

   배열을 사용해서 저장해도 되는데 사이즈를 따로 관리해야하는 번거로움이 있어서 vector를 이용했다.

   BFS에서 사용할 queue에 저장해서 넘겨주면 될 것 같지만 그렇게 되면 BFS가 한번 돌고 나면 queue에서 사라지므로 

   변형되지 않는 곳을 만들어서 저장해 두어야 한다.

2.3가지 종류의 벽의 조합을 모두 만들어야 하므로 DFS를 사용해야 한다.

3.벽을 만든 후에는 vector에 저장된 바이러스가 퍼지는 는 맵을 완성한다.

4.바이러스가 모두 퍼진 후 전염되지 않은 방의 갯수를 센다.

5.2번부터 다시 반복해서 바이러스가 전염되지 않은 방 갯수 중 가장 큰 경우를 찾으면 된다. 

 

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

int N,M;//행,열 
int map[8][8];
int tmp[8][8];//방문 표시
int dy[]={-1,1,0,0};//상하좌우
int dx[]={0,0,-1,1};
struct Q{
	int y,x;
};
queue<Q>q;
vector<Q>v;
int sol=0;
bool isInside(int a, int b){
	return ( (a>=0) && (a<N) && (b>=0) && (b<M));
}
int BFS(){	
	int count=0;
	//1.큐 초기화 
	q={};
	//2.큐에 초기값 입력 
    for(int i = 0; i < v.size(); i++)
        q.push(v[i]);
	//3.반복문 
	while(!q.empty()){
		Q cur=q.front();q.pop();
		for(int i=0; i<4; i++){
			int ny=cur.y+dy[i];
			int nx=cur.x+dx[i];
			if(isInside(ny,nx) && tmp[ny][nx]==0){
				tmp[ny][nx]=2;
				q.push({ny,nx});
			}	
		}
	}
	//4.return할 값 
	for(int i=0; i<N; i++){
		for(int j=0; j<M; j++){
			if(tmp[i][j]==0)
				count++;
		}
	}
	return count;
}
void copymap(){
	for(int i=0; i<N; i++){
		for(int j=0; j<M; j++){
			tmp[i][j]=map[i][j];
		}
	}
}
	
void DFS(int x, int d){
	if(d==3){
		copymap();//기존 map을 훼손하면 안되므로 임시 map에 저장함 
		sol=max(sol,BFS());//감염되지 않은 방중 최대값으로 업데이트 
		return;
	}
	for(int i=x; i<N; i++){
		for(int j=0; j<M; j++){
			if(map[i][j]==0){
				map[i][j]=1;
				DFS(i,d+1);
				map[i][j]=0;
			}
		}
	}

}
void Solve(){
	DFS(0,0);//맵에서 벽을 세울수 있는 경우를 DFS를 이용해서 조합으로 만듬
	cout<<sol<<endl;//오염되지 않은 방중 가장 큰값 
}
void InputData(){
	cin>>N>>M;
	for(int i=0; i<N; i++){
		for(int j=0; j<M; j++){
			cin>>map[i][j];
			if(map[i][j]==2){
				v.push_back({i,j});//바이러스 걸린 방을 따로 저장해 두어야한다. 
			}
		}
	}
}
int main(){
	InputData();
	Solve();
	return 0;
}
반응형

'Algorithm > BFS,DFS' 카테고리의 다른 글

[C++][BFS]백준 2589 보물섬  (0) 2022.04.11
[C++][백준]1520 내리막길  (0) 2022.04.10
[C++][백준]적록색약  (0) 2022.04.10
[c++][algoritm][baekjoon]7562 나이트의 이동  (0) 2021.09.23
[c++][algorithm][baekjoon][7569]토마토  (0) 2021.08.29
반응형

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

 

[풀이과정]

1.R,G,B 각 글자에 대해서 FloodFill을 이용해서 글자가 상하좌우에 연결된 부분을 찾는다.

2.전체 맵을 각 글자의 묶음들이 있는 걸 count해서 R,G,B 각 글자에 대해서 숫자를 count한다.

3.적록 색맹을 경우는 R를 G로 변경하는 작업을 해 준다.

4.1번 부터 동일한 과정으로 R,G에 대한 count를 해주면 된다.

/*백준 10026 적록색약*/
#include<iostream>
#include<memory.h>
using namespace std;
#define MAXN (int)1e2+10
char map[MAXN][MAXN];
int visited[MAXN][MAXN];//방문 표시
int N;//행,열 
int dy[]={-1,1,0,0};
int dx[]={0,0,-1,1};
bool isInside(int a, int b){
	return ( (a>=0) && (a<N) && (b>=0) && (b<N));
}
bool DFS(int y, int x, char c){	
	
	if(isInside(y,x) && visited[y][x]==0 && map[y][x]==c){
		visited[y][x]=1;
		for(int i=0; i<4; i++){
			DFS(y+dy[i],x+dx[i],c);
			//cout<<y+dy[i]<<' '<<x+dx[i]<<endl;
		}	
		return true;
	}else{
		return false;
	}
}
int Calc(int c){
	int cnt=0;
	for(int i=0; i<N; i++){
		for(int j=0; j<N; j++){
			if(map[i][j]==c)
				cnt+=DFS(i,j,c);
		}
	}
	return cnt;
}
void remap(){
	for(int i=0; i<N; i++){
		for(int j=0; j<N; j++){
			if(map[i][j]=='R')
				map[i][j]='G';
		}
	}
}
void Solve(){
	int cnt1=0,cnt2=0;
	cnt1+=Calc('R');
	cnt1+=Calc('G');
	cnt1+=Calc('B');
	memset(visited,false,sizeof(visited));
	remap();
	cnt2+=Calc('G');
	cnt2+=Calc('B');
	cout<<cnt1<<' '<<cnt2<<endl;
}
void InputData(){
	cin>>N;
	for(int i=0; i<N; i++){
			cin>>map[i];
	}
}
int main(){
	InputData();
	Solve();
	return 0;
}
반응형
반응형

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {1020, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000)

출력

 

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

 
예제 입력 1 
6
10 20 10 30 20 50
예제 출력 1 
4

8
10 20 30 5 10 20 30 40
정답: 5

반례 추가 
10
4 7 10 3 1 8 7 2 5 7
Answer: 4 
7
7 9 10 8 2 3 7
Answer: 3 
10
7 10 8 10 1 2 9 9 1 10
Answer: 4 
9
2 8 3 10 5 1 5 2 3
Answer: 3 
10
10 6 5 9 10 9 3 4 7 1
Answer: 3 
10
5 8 10 3 9 1 5 8 5 6
Answer: 3 
9
3 2 8 2 10 1 2 2 3
Answer: 3 
10
3 8 10 1 5 7 9 8 9 6
Answer: 5
7
4 3 4 9 1 3 7
Answer: 3 
10
8 6 8 9 5 1 4 4 6 3
Answer: 3

 

/*[12015]가장 긴 증가하는 부분 수열2*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN ((int)1e6+10)
int N; 
int A[MAXN];
vector<int> v;
auto it = v.begin();
void InputData(){
    cin >> N;
    for(int i=0; i<N; i++){
        cin >> A[i];
    }
}
void Solve(){
    v.push_back(A[0]);
    for(int i=1; i<N; i++){
        if(v.back() < A[i] ) v.push_back(A[i]);
        else {
            it = v.begin();
            it = lower_bound(v.begin(), v.end(), A[i]);
            *it = A[i];
        } 
    }
    cout << v.size() << endl;
}
int main(){
    InputData();
    Solve();
    return 0;
}
/*[12015]가장 긴 증가하는 부분 수열2*/
반응형
반응형

문제

세준이는 크기가 N×N인 배열 A를 만들었다. 배열에 들어있는 수 A[i][j] = i×j 이다. 이 수를 일차원 배열 B에 넣으면 B의 크기는 N×N이 된다. B를 오름차순 정렬했을 때, B[k]를 구해보자.

배열 A와 B의 인덱스는 1부터 시작한다.

입력

첫째 줄에 배열의 크기 N이 주어진다. N은 105보다 작거나 같은 자연수이다. 둘째 줄에 k가 주어진다. k는 min(109, N2)보다 작거나 같은 자연수이다.

출력

B[k]를 출력한다.

예제 입력 1 
3
7
예제 출력 1 
6

 

3
7
i: 1 lo:1 hi : 7 mid: 4 tmp: 3
i: 2 lo:1 hi : 7 mid: 4 tmp: 5
i: 3 lo:1 hi : 7 mid: 4 tmp: 6
i: 1 lo:5 hi : 7 mid: 6 tmp: 3
i: 2 lo:5 hi : 7 mid: 6 tmp: 6
i: 3 lo:5 hi : 7 mid: 6 tmp: 8
i: 1 lo:5 hi : 5 mid: 5 tmp: 3
i: 2 lo:5 hi : 5 mid: 5 tmp: 5
i: 3 lo:5 hi : 5 mid: 5 tmp: 6
6

반응형
반응형

문제

도현이의 집 N개가 수직선 위에 있다. 각각의 집의 좌표는 x1, ..., xN이고, 집 여러개가 같은 좌표를 가지는 일은 없다.

도현이는 언제 어디서나 와이파이를 즐기기 위해서 집에 공유기 C개를 설치하려고 한다. 최대한 많은 곳에서 와이파이를 사용하려고 하기 때문에, 한 집에는 공유기를 하나만 설치할 수 있고, 가장 인접한 두 공유기 사이의 거리를 가능한 크게 하여 설치하려고 한다.

C개의 공유기를 N개의 집에 적당히 설치해서, 가장 인접한 두 공유기 사이의 거리를 최대로 하는 프로그램을 작성하시오.

 

입력

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (0 ≤ xi ≤ 1,000,000,000)가 한 줄에 하나씩 주어진다.

출력

첫째 줄에 가장 인접한 두 공유기 사이의 최대 거리를 출력한다.

 

예제입력1
5 3
1
2
8
4
9

예제출력1
3

 

N : 집의 개수 

C : 공유기 개수 

이후 집의 좌표 

 

N : 3, C: 3

집의 좌표를 먼저 오름차순으로 정렬한다.

1 2 4 8 9

5 3
1
2
8
4
9
i: 1 X[i] : 2 lo:1 hi : 8 mid: 4 start: 1 cnt :1
i: 2 X[i] : 4 lo:1 hi : 8 mid: 4 start: 1 cnt :1
i: 3 X[i] : 8 lo:1 hi : 8 mid: 4 start: 8 cnt :2
i: 4 X[i] : 9 lo:1 hi : 8 mid: 4 start: 8 cnt :2
i: 1 X[i] : 2 lo:1 hi : 3 mid: 2 start: 1 cnt :1
i: 2 X[i] : 4 lo:1 hi : 3 mid: 2 start: 4 cnt :2
i: 3 X[i] : 8 lo:1 hi : 3 mid: 2 start: 8 cnt :3
i: 4 X[i] : 9 lo:1 hi : 3 mid: 2 start: 8 cnt :3
i: 1 X[i] : 2 lo:3 hi : 3 mid: 3 start: 1 cnt :1
i: 2 X[i] : 4 lo:3 hi : 3 mid: 3 start: 4 cnt :2
i: 3 X[i] : 8 lo:3 hi : 3 mid: 3 start: 8 cnt :3
i: 4 X[i] : 9 lo:3 hi : 3 mid: 3 start: 8 cnt :3
3

 

/*[2110]공유기 설치*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN ((int)2e5+10)
int N,C; //집의 개수, 공유기개수 
int X[MAXN];
long long M;

void InputData(){
    cin >> N >> C;
    for(int i =0; i<N; i++){
        cin >> X[i];
    }
}
void Solve(){
    int lo, hi, mid;
    long long sum;
    sort(X,X+N);
    lo = 1;
    hi = X[N-1] - X[0];
    int d = 0;
    int ans = 0;
    while(lo <= hi){
        mid=(lo+hi)/2; 
        int start = X[0];
        int cnt = 1;
        for(int i=1; i<N; i++){
            d = X[i] - start;
            if(mid <= d){
                ++cnt;
                start = X[i];
            }
       cout << "i: " << i << " X[i] : " << X[i] << " lo:" <<  lo  << " hi : " << hi  <<  " mid: " << mid <<  " start: " << start << " cnt :" << cnt  << endl;
         }
        if( cnt >= C){
            ans = mid;
            lo = mid + 1;
        }else{
            hi = mid - 1;
        }

        }
    cout << ans << endl;
}
int main(){
    InputData();
    Solve();
    return 0;
}
/*[2110]공유기 설치*/
반응형
반응형

문제

상근이는 나무 M미터가 필요하다. 근처에 나무를 구입할 곳이 모두 망해버렸기 때문에, 정부에 벌목 허가를 요청했다. 정부는 상근이네 집 근처의 나무 한 줄에 대한 벌목 허가를 내주었고, 상근이는 새로 구입한 목재절단기를 이용해서 나무를 구할것이다.

목재절단기는 다음과 같이 동작한다. 먼저, 상근이는 절단기에 높이 H를 지정해야 한다. 높이를 지정하면 톱날이 땅으로부터 H미터 위로 올라간다. 그 다음, 한 줄에 연속해있는 나무를 모두 절단해버린다. 따라서, 높이가 H보다 큰 나무는 H 위의 부분이 잘릴 것이고, 낮은 나무는 잘리지 않을 것이다. 예를 들어, 한 줄에 연속해있는 나무의 높이가 20, 15, 10, 17이라고 하자. 상근이가 높이를 15로 지정했다면, 나무를 자른 뒤의 높이는 15, 15, 10, 15가 될 것이고, 상근이는 길이가 5인 나무와 2인 나무를 들고 집에 갈 것이다. (총 7미터를 집에 들고 간다) 절단기에 설정할 수 있는 높이는 양의 정수 또는 0이다.

상근이는 환경에 매우 관심이 많기 때문에, 나무를 필요한 만큼만 집으로 가져가려고 한다. 이때, 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)

둘째 줄에는 나무의 높이가 주어진다. 나무의 높이의 합은 항상 M보다 크거나 같기 때문에, 상근이는 집에 필요한 나무를 항상 가져갈 수 있다. 높이는 1,000,000,000보다 작거나 같은 양의 정수 또는 0이다.

 

출력

적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 출력한다.

 

4 7
20 15 10 17
출력 : 15

5 20
4 42 40 26 46
출력:36

2 11
10 10
출력 : 4

3 1
1 2 2
출력 : 1
 
4 10
1 4 5 7
출력:2

5 2000000000
900000000 900000000 900000000 900000000 900000000
출력: 500000000

1 1000000000
1000000000
출력: 0

1 1
1000000000
출력: 999999999

6 12
19 9 18 20 17 8
출력: 15
 
5 14
4 22 10 16 36
출력: 22

풀이 과정 

나무수 N이 1,000,000개 이어서 이진 탐색으로 해서 찾아야 시간 초과 발생하지 않고 해결이 된다고 추측할 수 있다.

이진탐색색을 하기 위해서는 찾고자 하는 데이타를 오름차순 정렬을 해야 한다.

여기서 데이타는 나무 높이 데이타인 A를 정령해야 한다.

lo,hi값을 선정해야하는데, sorting후 제일 작은 값과 제일 큰 값으로 선정하면 된다. 

 

/*[2805]나무자르기*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN ((int)1e6+10)
int N;
int A[MAXN +10];
long long M;

void Solve(){
    int lo, hi, mid,sol=0;
    long long sum;
    sort(A,A+N);
    lo = 1;
    hi = A[N-1];
    while(lo <= hi){
        sum=0;
        mid=(lo+hi)/2; 
        for(int i=0; i<N; i++){
            if(A[i] > mid) sum += (A[i] - mid);
        }
        if(sum >= M){
            sol=mid;
            lo=mid+1;
        }else{
           hi = mid-1; 
        }
    }
    cout << sol << endl;
}
void InputData(){
    cin >> N >> M;
    for(int i =0; i<N; i++){
        cin >> A[i];
    }
}
int main(){
    InputData();
    Solve();
    return 0;
}
/*[2805]나무자르기*/
반응형

+ Recent posts