c++로 백준 문제 풀 시 다음 코드를 입력
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
BOJ
백준_골드
백준_골드_3
1.행렬 곱셈 순서(11049)
- 1.행렬 곱셈 순서(11049)
다이나믹프로그래밍을 이용하여 해결할 수 있는 문제
다이나믹프로그래밍 중 메모이제이션 방법 말고 2차원 행렬을 이용하여 바텀업 방식으로 해결할 수 있다.
가장 적은 횟수를 구하는 문제이므로 다이나믹프로그래밍 문제이다 이 때 이전 값을 계산하는 메모이제이션 방식이 아닌 구조를 분석하고 바텀업으로 해결하는 방식이다.
- 2차원 배열 생성
- 대각선을 기준으로 대칭행렬이며 주 대각 원소는 모두 0
- 바텀업 방식으로 계산해가면서 2차원 배열을 채워줌
#include <iostream>
#define MAX_SIZE 501
#define INF 2100000000
#define MIN(a,b) ((a)<(b)?(a):(b))
using namespace std;
int MatrixChain_DP(int *arr, int N);
int M[MAX_SIZE][MAX_SIZE];
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r" ,stdin);
int N = 0;
cin >> N;
int *arr = new int[N+1];
int a = 0;
int b = 0;
cin >> arr[0] >> arr[1];
for(int i=1; i<N; i++){
a = 0;
b = 0;
cin >> a >> b;
arr[i+1] = b;
}
int answer = MatrixChain_DP(arr,N);
cout << answer << "\n";
return 0;
}
int MatrixChain_DP(int *arr, int N)
{
int i,j,d;
for(int i=0; i<=N; i++){
for(int j=0; j<=N; j++)
M[i][j] = INF;
}
for(int i=1; i<=N; i++){
M[i][i] = 0;
}
int cost = 0;
int min = 0;
for(d=1; d<=N-1; d++)
{
for(i=1; i<=N-d; i++)
{
j= d+i;
for(int k=i; k<=j-1; k++){
cost = M[i][k] + M[k+1][j] + arr[i-1]*arr[k]*arr[j];
if(cost < M[i][j]){
M[i][j] = cost;
min = k;
}
}
}
}
return M[1][N];
}
백준_골드_4
1.백준(9252) LCS2
- 1.백준(9252) LCS2
최장공통부분수열 2번째 문제
LCS1과는 다르게 최장공통부분문자열을 출력해야 함
최장이므로 최적화 문제이다 따라서 다이나믹프로그래밍을 사용하여 문제를 해결
길이를 저장할 2차원 배열 L과 어느 위치에서 왔는지를 확인할 2차원 배열 S를 선언
bottom - up 방식으로 문제를 해결
- str1의 길이 n과 str2의 길이 m 둘 중 하나라도 0이면 비교할 문자가 없으므로 테이블을 0으로 초기화
- 문자열 비교
- 만약 문자가 같다면 왼쪽 대각선 +1
- 문자가 다르다면 왼쪽과 위쪽 중 더 큰 값으로 갱신
- 갱신과 동시에 어느쪽에서 왔는지를 S테이블에 저장
#include <iostream>
#define MAX_SIZE 1001
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int L[MAX_SIZE][MAX_SIZE];
// str1 == str2이 같다면 대각선에서
// str != str2이 다르다면 왼쪽과 위쪽 둘 중 더 큰값
int S[MAX_SIZE][MAX_SIZE];
// 0 => 왼쪽 대각
// 1 => 왼쪽
// 2 => 위
// 문자가 올 수 있는 위치 => 왼쪽 대각, 왼쪽, 위쪽
void LcsPrint(char *str1, char *str2, int n, int m);
int Len(char *str1);
int LCS2(char *str1, char *str2, int n, int m);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
char * str1 = new char[MAX_SIZE];
char * str2 = new char[MAX_SIZE];
cin >> str1 >> str2;
int str1Len = Len(str1);
int str2Len = Len(str2);
// cout << str1Len << " " << str2Len << "\n";
int answerNum = 0;
answerNum = LCS2(str1, str2, str1Len, str2Len);
cout << answerNum << "\n";
LcsPrint(str1, str2, str1Len, str2Len);
cout <<"\n";
return 0;
}
int LCS2(char * str1, char * str2, int n, int m)
{
for(int i=0; i<=n; i++)
L[i][0] = 0;
for(int j=0; j<=m; j++)
L[0][j] = 0;
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++)
{
if(str1[i-1] == str2[j-1]){
L[i][j] = L[i-1][j-1] +1;
S[i][j] = 0;
}
else
{
L[i][j] = MAX(L[i][j-1], L[i-1][j]); //왼쪽과 위 중 더 큰 값
if(L[i][j] == L[i][j-1]) // 만약 왼쪽에서 온 경우 1
S[i][j] = 1;
else
S[i][j] = 2;
}
}
}
return L[n][m];
}
int Len(char *str1)
{
char * temp = str1;
int cnt = 0;
while(*temp!=0)
{
temp ++;
cnt++;
}
return cnt;
}
void LcsPrint(char *str1, char *str2, int n, int m)
{
if(n==0 || m ==0)
return;
if(S[n][m] == 0) // 문자가 같았던 경우 다시 대각선으로 올라감
{
LcsPrint(str1, str2, n-1, m-1);
cout << str1[n-1] ;
}
else if(S[n][m]==1) // left
LcsPrint(str1, str2, n, m-1);
else
LcsPrint(str1, str2, n-1, m);
}
2.평범한 배낭(12865)
문제 설명
해당문제는 다이나믹프로그래밍을 이용하여 정해진 부피에 가방에 들어갈 수 있는 최대 가치를 구하는 문제이다. 만약 물건을 나눌 수 있다면 그리디기법으로 문제를 해결할 수 있지만 해당 문제는 물건을 나눌 수 없기 때문에 다이나믹 프로그래밍으로 접근해야 한다.
해결 방법
해당 테이블을 채우면서 만약에 해당 물건을 넣을 수 있는 공간이 없다면 자신을 넣기전 물건에 있는 최댓값을 넣어주고 공간이 있다면 둘 중 하나를 선택한다. 자신을 넣기전 최대 가치 또는 자신을 넣고 최대가치 이 방법으로 해결이 가능하다.
- 물건별 무게와 가치 정보를 담을 수 있는 구조체를 선언 후 입력
| 물건 | 무게 | 가치 | | — | — | — | | A | 3 | 13 | | B | 2 | 8 | | C | 1 | 6 |
- 세로축은 물건(i), 가로축은 최대 담을 수 있는 부피(j) 테이블을 생성
ex) 물건 : 3종류 , 최대 부피 4
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | | | | | | | B | | | | | | | C | | | | | |
- 최초 최대 부피가 0인경우 아무 물건도 넣을 수 없으므로 테이블을 모두 0으로 채운다
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | | | | | | B | 0 | | | | | | C | 0 | | | | |
- 이후 A물건부터 테이블을 채워간다 A물건이 들어가려면 최소 부피가 3이상이여야 하므로 그 이하는 모두 0을 채우고 3이상은 모두 A의 가치로 채운다.
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | 0 | 0 | 13 | 13 | | B | 0 | | | | | | C | 0 | | | | |
- 이후 다음과 같은 로직으로 DP테이블을 채운다.
- 해당 자리에 (B,1)에 물건 B가 들어갈 수 있는지 확인
- j인덱스 의미는 결국 가방안에 들어갈 수 있는 최대 부피를 말하므로 해당 크기보다 B물건의 부피가 더작거나 같다면 들어갈 수 있음
if(B.weight <= Bag[B][j])
- 만약 들어갈 수 있다면 해당 물건을 넣을지 말지 결정해야 함 즉 둘 중 더 큰 값을 선택(물건은 최대 한 번 밖에 못넣는다)
- 자기자신을 안넣는다면 자신의 테이블 위 가치를 선택
//B를 안넣고 A만 넣거나 A도 넣고 B도 넣을지 결정 Bag[A][j] or Bag[A][j-B.weight]
-
만약 해당 물건이 들어갈 수 없다면 그냥 자신을 넣기전 최댓값을 가져온다.
Bag[A][j]
DP
| 물건 | 무게 | 가치 | | — | — | — | | A | 3 | 13 | | B | 2 | 8 | | C | 1 | 6 |
- (B,1)
먼저 (B,1)의 경우 B의 무게는 2이고 현재 가방의 최대 부피는 1이므로 해당 테이블은 (A,1)의 값을 가져옴
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | 0 | 0 | 13 | 13 | | B | 0 | 0 | | | | | C | 0 | | | | |
- (B,2)
(B,2)의 경우 B의 무게는 2이고 현재 가방의 최대 부피는 2이므로 해당 테이블에 B물건을 넣을 수 있다. 이 때 해당 물건을 넣을지 말지 결정해야 하는데
- 자신을 넣지않고 A만 넣었을 때 (A,2) : 0
- 자신을 넣었을 때 (A,0) : 0, B.value(8) : 8 ⇒ 8
위와 같으므로 최댓값인 자신을 넣었을 때로 테이블 갱신
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | 0 | 0 | 13 | 13 | | B | 0 | 0 | 8 | | | | C | 0 | | | | |
- (B, 3)
(B, 3)의 경우 B를 넣을 수 있으므로 위와 같은 로직으로 접근
- 자신을 넣지않고 A만 넣었을 때 (A, 3) : 13
- 자신을 넣었을 때 (A,1) : 0 + B.value(8) : 8 ⇒ 8
위와 같으므로 최댓값인 자신을 넣지 않고 A만 넣었을 대로 테이블 갱신
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | 0 | 0 | 13 | 13 | | B | 0 | 0 | 8 | 13 | | | C | 0 | | | | |
- (B,4)
(B,4)의 경우 B를 넣을 수 있으므로 위와 같은 로직으로 접근
- 자신을 넣지않고 A만 넣었을 때(A,4) : 13
- 자신을 넣었을 대 (A,2) : 0 + B.value(8) : 8 ⇒ 8
위와 같으므로 최댓값 갱신
0 1 2 3 4 A 0 0 0 13 13 B 0 0 8 13 13 C 0 | 물건 | 무게 | 가치 | | — | — | — | | A | 3 | 13 | | B | 2 | 8 | | C | 1 | 6 |
- (C,1)
(C,1)의 경우 C의 무게는 1이고 해당 가방의 최대 부피는 1이므로 자신을 넣을지 말지 결정
- 자신을 넣지않고 B만 넣었을 때(B,1) : 0
- 자신을 넣었을 때 (B,0) : 0 + C.value(6) : 6 ⇒ 6
위와 같으므로 C를 넣어준다.
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | 0 | 0 | 13 | 13 | | B | 0 | 0 | 8 | 13 | 13 | | C | 0 | 6 | | | |
- (C,2)
(C,2)의 경우 최대부피가 2일 때 C를 넣을 수 있으므로 자신을 넣을지 말지 결정
- 자신을 넣지않고 B만 넣었을 때(B,2) : 8
- 자신을 넣었을 때 (B,1) : 0 + C.value(6) : 6 ⇒ 6
위와 같으므로 C를 넣지않고 B까지만 넣어준다.
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | 0 | 0 | 13 | 13 | | B | 0 | 0 | 8 | 13 | 13 | | C | 0 | 6 | 8 | | |
- (C,3)
(C,3)의 경우 최대부피가 3일 때 C를 넣을 수 있으므로 자신을 넣을지 말지 결정
- 자신을 넣지않고 B만 넣었을 때(B,3) : 13
- 자신을 넣었을 때 (B,2) : 8 + C.value(6) : 14
위와 같으므로 가방의 최대 부피가 3일 때 B와 C를 같이 넣은 14로 테이블을 갱신한다.
| | 0 | 1 | 2 | 3 | 4 | | — | — | — | — | — | — | | A | 0 | 0 | 0 | 13 | 13 | | B | 0 | 0 | 8 | 13 | 13 | | C | 0 | 6 | 8 | 14 | |
- (C,4)
(C,4)의 경우 최대부피가 4일 때 C를 넣을 수 있으므로 자신을 넣을지 말지 결정
- 자신을 넣지않고 B만 넣었을 때(B,4) : 13
- 자신을 넣었을 때 (B,3) : 13 + C.value(6) : 19
위와 같으므로 최댓값을 19로 갱신
0 1 2 3 4 A 0 0 0 13 13 B 0 0 8 13 13 C 0 6 8 14 19 위와 같은 방법으로 정답은 맨 마지막에 있는 19가 최댓값이 된다.
#include <iostream> #include <vector> #define MAX(a,b) (a) > (b) ? (a) : (b) using namespace std; typedef struct weight_value { int weight; int value; }wv; void print_bag(vector<vector<int> >&bag) { for(int i = 0; i<= bag.size(); i++){ for(int j = 0; j< bag[i].size(); j++){ cout << bag[i][j] << " "; } cout << "\n"; } } int main() { ios::sync_with_stdio(false); cin.tie(NULL); // freopen("input.txt", "r", stdin); int n = 0; int k = 0; cin >> n >> k; vector<weight_value>info; weight_value v; for(int i = 0; i<n; i++){ cin >> v.weight >> v.value; info.push_back(v); } vector<vector<int> >bag(n, vector<int>(k+1, 0)); // 1번 물건에 대해서 미리 테이블값을 설정 for(int w = 1; w<=k; w++){ if(info[0].weight<=w){ bag[0][w] = info[0].value; } } //1번 물건을 제외한 나머지부분 테이블 갱신 for(int i =1; i<n; i++){ for(int w=1; w<=k; w++){ if(w-info[i].weight >=0){ //해당 테이블에 물건을 넣을 공간이 있다면 // 자신을 넣기 전 최대가치 또는 자신을 넣을 공간을 제외한 공간 최대 가치 + 자신의 가치 중 더 큰걸 선택 bag[i][w] = MAX(bag[i-1][w], bag[i-1][w-info[i].weight] + info[i].value); } else //넣을 공간이 없다면 자신을 넣기 전 최대 가치로 갱신 bag[i][w] = bag[i-1][w]; } } // print_bag(bag); // 테이블에 맨 마지막 위치에는 최대 가치 저장 cout << bag[n-1][k] << "\n"; }
백준_골드_5
1.백준(7576) 토마토
너비우선탐색(BFS) 이용하여 정답을 구하는 문제이다
##### 시간초과가 계속 나는 이유를 찾아야 함.
### 시간초과 코드
- 문제에서 주어진 조건에 맞게 토마토 배열 생성
- 0 : 익지 않은 토마토
- 1 : 익은 토마토
- -1 : 아무것도 없음
- 좌표 구조체 생성
- 최단 거리 배열 생성
- 토마토 배열을 입력받을 때 미리 익은 토마토가 들어있는 좌표를 저장
- 반복문을 이용하여 토마토가 들어있는 좌표만 BFS실행
- 만약 반복도중 최소값을 갱신할 수 있다면 최소값 갱신
- 큐의 원소가 있다면 반복
- 현재 큐의 저장된 좌표를 빼고 pop()
- 대각선으로 갈 수없으므로 4방향만 체크
- 현재 좌표에서 4방향으로 갈 수있고 그 좌표가 이동가능한 좌표라면 즉 비어있지 않다면
- 새로운 좌표를 큐에 삽입
- 새로운 좌표의 재방문을 피하기 위해 다른값 으로 갱신
- BFS수행
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
int DAY;
int MAX;
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,-1,1};
typedef struct Point{
int x;
int y;
}Point;
void print(vector<vector<int> >&Tomato, int N, int M);
void BFS_TOMATO(vector<vector<int> >&Tomato, vector<vector<int> >&Distance ,queue<Point>&Q);
int findAnswer(vector<vector<int> >&Tomato);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin);
int N,M = 0;
cin >> M >> N ;
vector<vector<int> >Tomato(N, vector<int>(M, 0));
vector<vector<int> >Distance(N, vector<int>(M, 0));
Point P;
queue<Point>Q;
vector<Point>MAP;
for(int i=0; i<N; i++)
for(int j=0; j<M; j++){
cin >> Tomato[i][j];
if(Tomato[i][j] ==1){
P.x = j;
P.y = i;
MAP.push_back(P);
}
}
for(vector<Point>::iterator it = MAP.begin(); it!= MAP.end(); it++){
P.x = it->x;
P.y = it->y;
MAX = 0;
Q.push(P);
BFS_TOMATO(Tomato,Distance, Q);
DAY = DAY+2;
// print(Distance, N, M);
// cout <<"\n";
}
if(findAnswer(Tomato)){
return -1;
};
cout << MAX << "\n";
return 0;
}
void print(vector<vector<int> >&Tomato, int N, int M){
for(int i=0; i<N; i++){
for(int j=0; j<M; j++)
cout << Tomato[i][j] << " ";
cout << "\n";
}
} //테스트용
void BFS_TOMATO(vector<vector<int> >&Tomato,vector<vector<int> >&Distance, queue<Point>&Q){
if(!Q.empty()){
Point P1;
P1.x = Q.front().x;
P1.y = Q.front().y;
Q.pop();
int N = Tomato.size();
int M = Tomato[0].size();
for(int i=0; i<4; i++){
// 4방향 탐색
Point P2;
P2.x = P1.x + dx[i];
P2.y = P1.y + dy[i];
if( (P2.x >=0 && P2.x < M) && (P2.y >=0 && P2.y <N) ){
// 인덱스 범위안에 있다면
if(Tomato[P2.y][P2.x]==DAY){
Tomato[P2.y][P2.x] = DAY+2;
if(Distance[P2.y][P2.x]!=0){
Distance[P2.y][P2.x] = min(Distance[P1.y][P1.x]+1,Distance[P2.y][P2.x]);
}
else{
Distance[P2.y][P2.x] = Distance[P1.y][P1.x] +1;
}
if(MAX <=Distance[P2.y][P2.x] ){
MAX = Distance[P2.y][P2.x];
}
Q.push(P2);
}
}
}
BFS_TOMATO(Tomato, Distance, Q);
}
}
int findAnswer(vector<vector<int> >&Tomato){
int N = Tomato.size();
int M = Tomato[0].size();
for(int i=0; i<N; i++)
for(int j=0; j<M; j++)
if(Tomato[i][j] ==0)
return 1;
return 0;
}
### 정답 코드 ##### 따로 따로 너비탐색을 하는게 아니라 동시에 진행했어야 한다....
- 주어진 조건에 맞게 토마토 입력
- 익은 토마토가 나올때마다 큐에 삽입
- while반복문을 돌면서 큐에 원소를 빼서 너비탐색 시작 - 예제 3번같은 경우 최초 큐에 [ (0,0) , (2,5) ]가 삽입되어있고 - 1번 BFS탐색 시 (0,0)에서 그래프 탐색을 먼저 하고 그 다음에 큐에 삽입 되기전에 미리 있던 (2,5)좌표가 BFS탐색이 시작된다. - 따라서 먼저 (0,0) 탐색 그 다음(2,5)에서 탐색이 된다.
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
vector<vector<int> >Box(1001, vector<int>(1001, 0));
// 토마토 박스정보
queue<pair<int, int> >Q;
int dx[4] = {-1,1, 0, 0};
int dy[4] = {0, 0, -1, 1};
// 4방향 탐색
int N;
int M;
int MAX;
void BFS(){
while(!Q.empty()){
int y = Q.front().first;
int x = Q.front().second;
Q.pop();
// 좌표 삽입
for(int i=0; i<4; i++){
// 4방향 탐색
int X = x + dx[i];
int Y = y + dy[i];
if((X>=0 && X<M) && (Y>=0 && Y<N)){
if(Box[Y][X] ==0){
// 인덱스 범위 내에 있고 익지않은 토마토라면
Box[Y][X] = Box[y][x] +1;
// 하나씩 증가
Q.push(make_pair(Y,X));
}
}
}
}
}
int findAnswer(){
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
if(Box[i][j] ==0 )
// 익지않은 토마토가 하나라도 있다면 답없음
return 1;
if(MAX < Box[i][j]){
MAX = Box[i][j];
}
// 맥스값 갱신
}
}
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int n,m = 0;
cin >> m >> n;
N = n;
M = m;
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
int temp = 0;
cin >> temp ;
// 익은 토마토가 나온다면 큐에 삽입
if(temp==1)
Q.push(make_pair(i,j)); //y먼저 삽입
Box[i][j] = temp;
}
}
BFS();
// BFS탐색 시작
if(findAnswer())
cout << -1 <<"\n";
else
cout << MAX-1 <<"\n";
return 0;
}
2.백준(10026) 적록색약
너비우선탐색(BFS) 또는 깊이우선탐색(DFS)를 이용하여 정답을 구하는 문제이다
일반인인 경우의 계산이 끝나고 난 후 초록색을 전부 빨강색으로 바꾼 뒤 연산하였는데 답이 나오지 않음
실패코드
#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void Print(vector<vector<string> >&Map, int N){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
cout << Map[i][j] << " ";
}
cout <<"\n";
}
}
void print(vector<vector<int> >&Map, int N){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
cout << Map[i][j] << " ";
}
cout <<"\n";
}
}
void init(vector<vector<int> >&visit){
for(int i=0; i<visit.size(); i++){
for(int j=0; j<visit.size(); j++){
visit[i][j] = 0;
}
}
}
void Init(vector<vector<string> >&map){
for(int i=0; i<map.size(); i++){
for(int j=0; j<map.size(); j++){
if(map[i][j] == "G"){
map[i][j] = "R";
}
}
}
}
typedef struct Point{
int x;
int y;
}point;
void BFS(vector<vector<string> >&Map, vector<vector<int> >&visit, queue<point>&Q, string s){
while(!Q.empty()){
point P;
int N = Map.size();
P.x = Q.front().x;
P.y = Q.front().y;
Q.pop();
for(int i=0; i<4; i++){
point new_point;
new_point.x = P.x + dx[i];
new_point.y = P.y + dy[i];
if( (new_point.x>=0 && new_point.x<N) && (new_point.y>=0 && new_point.y<N)){
if(visit[new_point.y][new_point.x] ==0 && Map[new_point.y][new_point.x] == s){
visit[new_point.y][new_point.x]=1;
Q.push(new_point);
}
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
vector<vector<string> >Map(N, vector<string>(N));
vector<vector<int> >visit(N, vector<int>(N,0));
for(int i =0; i<N; i++){
string str;
cin >> str;
for(int j=0; j<str.length(); j++)
Map[i][j] = str[j];
}
queue<point>Q;
point p ;
string s;
int notRedGreen = 0;
int RedGreen = 0;
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(visit[i][j]==0){
visit[i][j] = 1;
p.x = j;
p.y = i;
s = Map[i][j];
Q.push(p);
BFS(Map,visit, Q,s);
notRedGreen ++;
// break;
}
}
}
init(visit);
Init(Map);
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(visit[i][j]==0){
visit[i][j] = 1;
p.x = j;
p.y = i;
s = Map[i][j];
Q.push(p);
BFS(Map,visit, Q,s);
RedGreen ++;
break;
}
}
}
cout << notRedGreen << " " << RedGreen << "\n";
// Print(Map, N);
// print(visit, N);
return 0;
}
반례
5 BBBBG GRBBB BBBBB BBBBB RRRRR
정답: 5 4 출력: 4 3
성공
2번째 탐색 때 브레이크를 걸어서 끝까지 탐색이 안된거였다….. 실수하지말자…
#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void Print(vector<vector<string> >&Map, int N){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
cout << Map[i][j] << " ";
}
cout <<"\n";
}
}
void print(vector<vector<int> >&Map, int N){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
cout << Map[i][j] << " ";
}
cout <<"\n";
}
}
void init(vector<vector<int> >&visit){
for(int i=0; i<visit.size(); i++){
for(int j=0; j<visit.size(); j++){
visit[i][j] = 0;
}
}
}
void Init(vector<vector<string> >&map){
for(int i=0; i<map.size(); i++){
for(int j=0; j<map.size(); j++){
if(map[i][j] == "G"){
map[i][j] = "R";
}
}
}
}
typedef struct Point{
int x;
int y;
}point;
void BFS(vector<vector<string> >&Map, vector<vector<int> >&visit, queue<point>&Q, string s){
while(!Q.empty()){
point P;
int N = Map.size();
P.x = Q.front().x;
P.y = Q.front().y;
Q.pop();
for(int i=0; i<4; i++){
point new_point;
new_point.x = P.x + dx[i];
new_point.y = P.y + dy[i];
if( (new_point.x>=0 && new_point.x<N) && (new_point.y>=0 && new_point.y<N)){
if(visit[new_point.y][new_point.x] ==0 && Map[new_point.y][new_point.x] == s){
visit[new_point.y][new_point.x]=1;
Q.push(new_point);
}
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
vector<vector<string> >Map(N, vector<string>(N));
vector<vector<int> >visit(N, vector<int>(N,0));
for(int i =0; i<N; i++){
string str;
cin >> str;
for(int j=0; j<str.length(); j++)
Map[i][j] = str[j];
}
queue<point>Q;
point p ;
string s;
int notRedGreen = 0;
int RedGreen = 0;
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(visit[i][j]==0){
visit[i][j] = 1;
p.x = j;
p.y = i;
s = Map[i][j];
Q.push(p);
BFS(Map,visit, Q,s);
notRedGreen ++;
}
}
}
init(visit);
Init(Map);
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(visit[i][j]==0){
visit[i][j] = 1;
p.x = j;
p.y = i;
s = Map[i][j];
Q.push(p);
BFS(Map,visit, Q,s);
RedGreen ++;
}
}
}
cout << notRedGreen << " " << RedGreen << "\n";
// Print(Map, N);
// print(visit, N);
return 0;
}
3.백준(9251) LCS
최장공통부분스트링을 찾는 최적화 문제이다
최장 => 최적화 => DP => 점화식 => Working Backward
최적화문제는 DP로 해결가능하며 DP를 생각했다면 구조를 파악해서 점화식을 세운다.
배우고나면 그닥 어렵지 않은 문제이다.
- 조건에 맞게 String을 입력받음
- Memoization을 사용해야 하므로 최대 사이즈의 2차원 배열을 미리 선언
- 배열의 값을 -1로 초기화
- str1 또는 str2의 사이즈가 0이 있다면 더 이상 최장부분이 없으므로 0리턴
- 만약 str1과 str2의 값이 같다면
- 2차원배열의 값을 재귀적으로 갱신 후 return
- 2차원 배열의 대각선의 값 +1
- 만약 값이 다르다면
- 2차원배열의 값을 재귀적으로 갱신 후 return
- 2차원배열의 왼쪽과 위쪽 중 더 Max값으로 값을 갱신
#include <iostream>
#define MAX_SIZE 1001
#define MAX(a,b) ((a)>(b)?(a):(b))
int L[MAX_SIZE][MAX_SIZE];
using namespace std;
int Len(char *str);
int LCS_Memoization(char *str1, char *str2, int M, int N);
void init();
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt" , "r", stdin);
char str1[MAX_SIZE];
char str2[MAX_SIZE];
cin >> str1 >> str2;
int M = Len(str1);
int N = Len(str2);
init();
int answer = LCS_Memoization(str1,str2,M,N);
cout << answer << "\n";
return 0;
}
int Len(char *str){
int cnt = 0;
char * temp = str;
while(*temp!=0){
cnt++;
temp++;
}
return cnt;
}
int LCS_Memoization(char *str1, char *str2, int M, int N){
if(M==0 || N==0)
return 0;
if(L[M-1][N-1]!=-1)
return L[M-1][N-1];
else{
if((M>0 && N>0) && (str1[M-1]) == (str2[N-1])){
L[M-1][N-1] = (LCS_Memoization(str1,str2, M-1, N-1))+1;
return L[M-1][N-1];
}
else if((M>0 && N>0) && (str1[M-1]) != (str2[N-1])) {
int left = LCS_Memoization(str1,str2,M,N-1);
int right = LCS_Memoization(str1,str2,M-1,N);
int max = MAX(left, right);
L[M-1][N-1] = max;
return L[M-1][N-1];
}
else
return 0;
}
}
void init(){
for(int i=0; i<MAX_SIZE; i++){
for(int j=0; j<MAX_SIZE; j++){
L[i][j] = -1;
}
}
}
DP버전 최장길이뿐 아니라 어떠한 문자열인지도 알 수 있음
#include <iostream>
#define MAX_SIZE 101
#define MAX(a,b) ((a)>(b)?(a):(b))
int L[MAX_SIZE][MAX_SIZE];
int S[MAX_SIZE][MAX_SIZE];
using namespace std;
int Len(char *str);
int LCS_DP(char *str1, char *str2, int M, int N);
void printLCS(char *str1, char *str2,int M, int N);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt" , "r", stdin);
int testCase = 0;
cin >> testCase;
while(testCase--){
char str1[MAX_SIZE];
char str2[MAX_SIZE];
cin >> str1 >> str2;
int M = Len(str1);
int N = Len(str2);
int answer = LCS_DP(str1,str2,M,N);
cout << answer << " ";
printLCS(str1,str2,M,N);
cout <<"\n";
}
return 0;
}
int Len(char *str){
int cnt = 0;
char * temp = str;
while(*temp!=0){
cnt++;
temp++;
}
return cnt;
}
int LCS_DP(char *str1, char *str2, int M, int N){
for(int i=0; i<=M; i++)
L[i][0] = 0;
for(int i=0; i<=N; i++)
L[0][i] = 0;
for(int i=1; i<=M; i++){
for(int j=1; j<=N; j++){
if(str1[i-1] == str2[j-1]){
L[i][j] = L[i-1][j-1]+1; // 문자가 같으면 대각선 +1
S[i][j] = 0;
}
else{
L[i][j] = MAX(L[i][j-1], L[i-1][j]); //다르면 왼쪽 오른쪽 중 큰거
if(L[i][j] == L[i][j-1])
S[i][j] = 1;
else
S[i][j] = 2;
}
}
}
return L[M][N];
}
void printLCS(char *str1, char *str2,int M, int N){
if(M==0 || N==0)
return;
if(S[M][N] ==0){
printLCS(str1, str2, M-1, N-1);
cout << str1[M-1];
}
else if(S[M][N]==1)
printLCS(str1, str2, M, N-1);
else if(S[M][N]==2)
printLCS(str1, str2, M-1, N);
}
———————-
백준_실버
백준_실버_1
1.백준(2178) 미로탐색
- 1.백준(2178) 미로탐색
너비우선탐색(BFS)를 이용하여 최단거리를 탐색하는 문제이다..
가중치가 없는 그래프에서는 BFS를 이용하면 최단거리를 탐색할 수 있다.
- 문제에서 주어진 조건에 맞게 지도(Map)을 생성
- 0은 벽이며 1은 지날 수 있는 길이다.
- 각 좌표마다의 최단거리를 저장할 거리 배열을 생성
- 이동이 가능할 경우 이전 좌표에서 +1을 해주는식으로 이동한다.
- 최초 0,0을 Queue에 넣어주면서 시작한다.
- 문제에서 주어진 조건에 맞게 지도(Map)을 생성
- 큐의 원소가 있다면 반복실행
- 현재 Queue의 저장된 좌표를 빼고 pop()
- 미로를 대각선으로 갈 수없으므로 4방향만 체크
- 현재 좌표에서 4방향으로 갈 수있고 그 좌표가 이동가능한 좌표라면 즉 벽이 아니라면
- 새로운 좌표를 Queue에 삽입
- 새로운 좌표의 재방문을 피하기 위해 0으로 갱신
- 거리 좌표를 이전 값 +1 로 갱신
- 만약 Distance 배열의 [N-1][M-1] 값이 0이라면 탐색이 실패한 경우고 값이 저장되어있다면 그 값이 최단거리이다
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct point{
int x;
int y;
}Point;
int dx[4] ={-1, 1, 0, 0};
int dy[4]= {0, 0, -1, 1};
// 오른쪽 왼쪽 아래 위
void print(vector<vector<int> >Map, int N, int M){
for(int i=0; i<N; i++){
for(int j=0; j<M; j++)
cout << Map[i][j] << " ";
cout << "\n";
}
}
void Find(vector<vector<int> >&Map, vector<vector<int> >&Distance, queue<Point> &Search ,int N, int M){
// x,y 좌표 저장용
Point P;
P.x = 0;
P.y = 0;
Search.push(P);
while(!Search.empty()){ // Queue의 원소가 하나라도 있다면 반복 실행
P.x = Search.front().x;
P.y = Search.front().y;
Search.pop();
for(int i=0; i<4; i++){ // 오른쪽 왼쪽 아래 위
int new_X = P.x + dx[i];
int new_Y = P.y + dy[i];
if( (0 <= new_X && new_X< M) && (0 <= new_Y && new_Y < N)){
if( Map[new_Y][new_X] == 1 ){
// 탐색이 범위안에 있으며 벽이 아닌 경우
Point new_P;
new_P.x = new_X;
new_P.y = new_Y;
Map[new_Y][new_X] = 0; //재탐색을 방지하기 위하여 이미 지나간 좌표는 벽으로
Distance[new_Y][new_X] = Distance[P.y][P.x] +1; //이전 값 +
Search.push(new_P); // 탐색 가능한 좌표 갱신
}
}
} // 네 방향 확인
} //while문
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N , M= 0;
cin >> N >> M;
vector<vector<int> >Distance(N, vector<int>(M, 0));
// 최단 방문거리를 확인하기 위하여 생성
vector<vector<int> >Map(N, vector<int>(M));
// 현재 가능한 이동가능한 지도 배열 생성
string Maze;
for(int i=0; i<N; i++){
cin >> Maze;
for(int j=0; j<Maze.length(); j++)
Map[i][j] = Maze[j]-48;
}
// print(Map, N, M);
queue<Point>Search;
Distance[0][0] = 1;
Map[0][0] = 0;
//최초 시작 셋팅
Find(Map, Distance, Search, N, M); //최단거리 함수
// 위 함수가 끝났을 때 Distance 배열에는 각각 좌표마다 최단 거리가 저장되어 있다
// 만약 Distance 배열의 [N-1][M-1] 값이 0이라면 탐색이 실패한 경우고 값이 저장되어있다면 그 값이 최단거리이다
// 현재 문제에서 탐색이 불가능한 경우는 주어지지 않았으므로 그냥 Distance[N-1][M-1]을 출력해도 상관없다.
// 배열의 인덱스는 0부터 시작이므로 주어진 좌표-1을 해야한다
if(Distance[N-1][M-1]!=0)
cout << Distance[N-1][M-1] << "\n";
return 0;
}
2.백준(2667) 단지붙이기
너비우선탐색(BFS) 또는 깊이우선탐색(BFS)를 이용하여 단지의 개수를 구하는 문제이다
DFS로 한번에 구하는게 아니라 for문을 통해서 구할 수 있다.
- 문제에서 주어진 조건에 맞게 지도(Map)을 생성
- 0은 빈 집이며 1은 집이다.
- 좌표 구조체 생성
- 단지마다 숫자를 저장 할 구조체와 배열 생성
- 반복문을 이용하여 맵의 전체를 돌아다니면서 집이 있는 곳에서 DFS 실행하고 단지의 갯수를 반환 후 배열의 저장
- 조건에 맞게 오름차순으로 정렬
- 스택의 원소가 있다면 반복
- 현재 Stack의 저장된 좌표를 빼고 pop()하고 숫자를 1증가
- 미로를 대각선으로 갈 수없으므로 4방향만 체크
- 현재 좌표에서 4방향으로 갈 수있고 그 좌표가 이동가능한 좌표라면 즉 비어있지 않다면
- 새로운 좌표를 Stack에 삽입
- 새로운 좌표의 재방문을 피하기 위해 0으로 갱신
- DFS수행
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
typedef struct Dic{
int Number;
int Count;
}Dic;
// 단지의 정보를 저장할 구조체 선언
typedef struct Point{
int x;
int y;
}Point;
// 단지의 좌표를 저장할 구조체 선언
void Print(vector<vector<int> >&map, int n);
int makeBuildings(vector<vector<int> >&map, stack<Point>&s, int i, int j, int cnt);
bool com(Dic a, Dic b);
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,-1,1};
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
freopen("input.txt" , "r", stdin);
int N= 0;
cin >> N;
vector<vector<int> >map(N, vector<int>(N, 0));
for(int i=0; i<N; i++){
string str;
cin >> str;
for(int j=0; j<str.length(); j++)
map[i][j] = str[j]-48;
}
// 주어진 조건에 맞게 Map배열의 삽입
// Print(map,N);
vector<Dic>answer;
stack<Point>s;
Dic d;
Point p;
int dange = 1;
int cnt = 0; //집 갯수를 저장할 변수
for(int i=0; i<N; i++){ //모든 Map을 방문
for(int j=0; j<N; j++){
if(map[i][j] ==1){ //만약 빈 집이아니라면
cnt = 0;
p.x = j;
p.y = i;
s.push(p); //현재 좌표를 스택의 push
d.Count = makeBuildings(map,s, i,j,cnt); //DFS연산 시작
d.Number = dange++;
answer.push_back(d); //카운터 값 저장
}
}
}
stable_sort(answer.begin(), answer.end(), com);
// 오름차순 정렬
cout << answer.size() << "\n";
for(vector<Dic>::iterator it = answer.begin(); it!= answer.end(); it++)
cout << it->Count << "\n";
return 0;
}
bool com(Dic a, Dic b){
return a.Count < b.Count;
} //단지의 갯수로 오름차순 정렬
void Print(vector<vector<int> >&map, int N){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++)
cout << map[i][j] <<" ";
cout << "\n";
}
} //확인용
int makeBuildings(vector<vector<int> >&map, stack<Point>&s, int i, int j, int cnt){
if(!s.empty()){
Point p;
p.x = s.top().x;
p.y = s.top().y;
s.pop();
map[p.y][p.x] = 0;
cnt ++;
int size = map.size();
for(int k=0; k<4; k++){
Point NP;
NP.x = p.x+dx[k];
NP.y = p.y+dy[k];
if((NP.x>=0 && NP.x<size) && (NP.y>=0 && NP.y<size)){
if(map[NP.y][NP.x] == 1){
map[NP.y][NP.x] = 0;
s.push(NP);
cnt = makeBuildings(map,s,NP.y,NP.x, cnt);
}
}
}
}
return cnt;
}
3.백준(1697) 숨바꼭질
너비우선탐색(BFS)을 이용하여 최단 경로를 찾는 문제이다
BFS를 이용하여 주어진 조건에 맞게 탐새하고 종료조건만 추가해주면 쉽게 해결이 가능했다.
- 조건에 맞게 최대사이즈 배열을 생성
- 앞,뒤 그리고 2배 보폭으로 최단거리 탐색
- 원하는 목적지까지 최단거리 탐색이 끝나면 Flag를 바꿔서 바로 종료
- 최초 시작점을 1로 설정했으므로 정답은 -1을 해준다.
- 큐의 원소가 있다면 반복
- 현재 큐의 저장된 좌표를 빼고 pop()
- 앞뒤, 그리고 2배 보폭으로 탐색 (3방향)
- 현재 좌표에서 3방향으로 갈 수있고 탐색이 이루어지지 않았다면
- 새로운 좌표를 Queue 삽입
- BFS수행
#include <iostream>
#include <queue>
using namespace std;
int N;
int K;
int FLAG;
vector<int>Visit(100001,0);
queue<int>Q;
int dpoint[2] = {-1,1};
void BFS();
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int n, k= 0;
cin >> n >> k;
N = n;
K = k;
Q.push(N);
Visit[N] = 1;
FLAG = false;
BFS();
cout << Visit[k]-1<<"\n";
// cout << "ANSWER IS " << Visit[k]-1 <<"\n";
return 0;
}
void BFS(){
while(!Q.empty()){
int Point;
int point = Q.front();
Q.pop();
for(int i=0; i<3; i++){
if(i==2)
Point = point * 2;
else{Point = point + dpoint[i];}
if(Point>=0 && Point <100001){
if(Visit[Point]==0){
Visit[Point] = Visit[point]+1;
if(Point==K){FLAG = true; break;}
// 원하는 목적지까지 탐색이 완료되었으면 플래그를 true로 바꾸고 종료
Q.push(Point);
}
}
}
if(FLAG == true){break;}
}
}
4.백준(1931) 회의실 배정
그리디 알고리즘을 이용하여 푸는 문제이다 정렬만 잘 사용한다면 어렵지는 않다.
sort를 정의함에 있어서 종료시간이 같을 때 정렬기준을 else if로 하면 segment falut에러가 뜬다..
- 주어진 조건에 맞게 구조체를 선언
- 반복문을 둘면서 구조체 벡터에 주어진 시작과 종료시간을 삽입
- 종료시간을 기준으로 정렬 -> 종료시간이 같다면 시작시간을 기준으로 정렬
- 반복문을 통해서 제일 빠른 순서부터 내려오면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct conference{
int start;
int end;
}conference;
bool com(conference a, conference b){
if(a.end < b.end)
return true;
if(a.end ==b.end){
//else if로 하면 segment falut뜸 ... 왜 그럴까
return a.start < b.start;
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int Num = 0;
cin >> Num;
conference C ;
vector<conference>Answer;
for(int i=0; i<Num; i++){
cin >> C.start >> C.end;
Answer.push_back(C);
}
sort(Answer.begin(), Answer.end(), com);
// 종료시점을 기준으로 정렬
int temp = 0;
int answer = 1;
temp =Answer[0].end;
for(int i=1; i<=Num; i++){
// 종료시간보다 같거나 느린 시작시간이 있다면 갱신
if(temp <= Answer[i].start){
answer ++;
temp = Answer[i].end;
}
}
cout << answer << "\n";
return 0;
}
5.백준(13335) 트럭
큐를 이용하여 구현하는 문제이며 대기 트럭이 다리에 오르지 못했을 경우 처리방법을 생각하기 어려웠다.
시간이 흐름에 따라 트럭이 다리를 지나간다라는 것을 표현하기 어려웠으나 좋은 경험이 되었다.
- 주어진 조건에 맞게 대기 트럭과 다리에 현재 있는 트럭을 표현할 큐 생성
- 대기 트럭을 꺼내서 만약 다리에 올릴 수 있다면 맨 앞 트럭 제거 후 현재 트럭 삽입
- 대기 트럭을 꺼내서 만약 다리에 올릴 수 없다면 0을 삽입해줌
- 맨 마지막 트럭은 그냥 보내면 되므로 현재 정답 + 다리의 길이를 더해줌
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int numOftrucks = 0;
int bridge_len = 0;
int weight = 0;
cin >> numOftrucks >> bridge_len >> weight;
vector<int>Trucks(numOftrucks,0);
for(int i=0; i<numOftrucks; i++)
cin >> Trucks[i];
queue<int>wait;
queue<int>passing;
int len = bridge_len;
for(int i=0; i<len; i++)
passing.push(0);
// 주어진 다리 길이에 맞게 최초 0을 삽입한 큐 생성
for(auto t : Trucks)
wait.push(t);
// 트럭 정보 입력
int answer = 0;
int W = 0;
int temp = 0;
// 정답과 현재 다리의 총 무게, 건너야하는 트럭 정보 변수 선언
while(!wait.empty()){ //대기 트럭이 있는동안 반복
answer ++;
// 1초가 지나고
temp = wait.front(); //대기 트럭 정보 저장
W = W-passing.front(); // 다리를 건넌 트럭은 무게에서 제외
passing.pop(); // 다리에 제일 선두에 있는 트럭 제거
if( W + temp <= weight){ // 현재 다리 총 무게 + 대기 트럭이 건널 수 있으면
W = W+temp; wait.pop(); // 대기 트럭 다리에 올리고
passing.push(temp); //한 칸 전진
}
else{
passing.push(0); // 만약 대기 트럭을 못 올린다면 0으로 채움
}
} //while
answer = answer + bridge_len; //마지막 트럭만 보내면 끝임
cout << answer <<"\n";
return 0;
}
6.백준(11403) 경로 찾기
방향 그래프에서 정점간에 관계를 파악하는 문제이다 플로이드 워셜 또는 BFS로 해결이 가능하다.
다음번에는 BFS가 아닌 플로이드 워셜 방법을 활영해보자
- 주어진 조건에 맞게 그래프 관계 파악
- BFS탐색
- 최종 방문 현황 벡터를 출력
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void print(vector<int>Graph[], int N){
for(int i=1; i<=N; i++){
for(vector<int>::iterator it = Graph[i].begin(); it!= Graph[i].end(); it++){
cout << *it << " ";
}
cout << "\n";
}
} //확인용
void BFS(vector<int>Graph[], vector<vector<int> >&Visit , queue<int>&Q, int Start){
while(!Q.empty()){
int idx = Q.front();
Q.pop();
for(vector<int>::iterator it = Graph[idx].begin(); it!= Graph[idx].end(); it++){
if(Visit[Start][*it]==0){
Visit[Start][*it]=1;
Q.push(*it);
}
}
}
} //BFS탐색 시작
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N =0 ;
cin >> N;
vector<int>Graph[N+1];
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
int temp = 0;
cin >> temp;
if(temp == 1)
Graph[i].push_back(j);
}
} // 주어진 조건에 맞게 방향 그래프관계 표현
vector<vector<int> > Visit(N+1, vector<int>(N+1, 0)); //방문 및 정답 벡터 생성
for(int i=1; i<=N; i++){
queue<int>Q;
Q.push(i);
BFS(Graph,Visit,Q, i);
}
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
cout << Visit[i][j] << " ";
}
cout <<"\n";
}
return 0;
}
7.백준(7562) 나이트의 이동
가중치가 없는 그래프에서의 최단거리 알고리즘인 BFS를 이용하여 해결하는 문제이다.
Call by value로 하면 메모리 초과가 나는 문제이다
- 주어진 조건에 맞게 Vector 생성
- 시작점을 체크한 후 BFS탐색
- TargetPoint 탐색 완료시 종료
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef struct Point{
int x;
int y;
}point;
void Bfs(vector<vector<int> >&map,vector<vector<int> >&visit, queue<point>&q , point &targetPoint);
void CheckVector(vector<vector<int> >&v, int size);
int dy[8] = {-2,-1,1,2,2,1,-1,-2};
int dx[8] = {1,2,2,1,-1,-2,-2,-1};
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int testCase = 0;
cin >> testCase;
while(testCase--){
int N = 0;
point p;
point targetPoint;
cin >> N;
vector<vector<int> >map(N,vector<int>(N,0));
vector<vector<int> >visit(N,vector<int>(N,0));
cin >> p.y >> p.x;
cin >> targetPoint.y >> targetPoint.x;
if ((p.y == targetPoint.y) && (p.x == targetPoint.x)){
cout << 0 <<"\n";
}
else{
visit[p.y][p.x] = 1;
queue<point>q;
q.push(p);
Bfs(map,visit,q, targetPoint);
// CheckVector(map, map.size());
if(map[targetPoint.y][targetPoint.x]!=0){
cout << map[targetPoint.y][targetPoint.x] <<"\n";
}
}
}
return 0;
}
void Bfs(vector<vector<int> >&map,vector<vector<int> >&visit, queue<point>&q , point &targetPoint){
if(!q.empty()){
int size = map.size();
point p;
p.x = q.front().x;
p.y = q.front().y;
q.pop();
for(int i=0; i<8; i++){
point P;
P.y = dy[i] + p.y;
P.x = dx[i] + p.x;
if((P.y>=0 && P.y<size) && (P.x>=0 && P.x <size)){ //index 범위안에 존재
if(visit[P.y][P.x]==0){ //최초 방문
visit[P.y][P.x] = 1;
map[P.y][P.x] = map[p.y][p.x]+1;
if((P.y == targetPoint.y) && (P.x == targetPoint.x)){
return ;
}
q.push(P);
}
}
}
Bfs(map,visit,q,targetPoint);
}
}
void CheckVector(vector<vector<int> >&v, int size){
for(int i=0; i<size; i++){
for(int j=0; j<size; j++){
cout << v[i][j] <<" ";
}
cout <<"\n";
}
}
8.백준(1932) 정수 삼각형
- 1.백준(2178) 미로탐색 해당문제는 다이나믹프로그래밍을 이용하여 해결하는 문제이다. 해당 문제를 dfs로 해결하면 중복되는 계산이 너무 많아 시간초과를 피할 수 없다. 따라서 해당 문제는 정수 삼각형을 계산함과 동시에 최댓값을 업데이트하는 다이나믹 프로그래밍 기법으로 해결해야한다. 위에서 내려오면서 j가 0인경에는 무조건 위에서 내려오는 최대합을 구하고 나머지는 \대각선 방향과 | 일자 방향에서의 누적합 중 최댓값을 구해주면 되는 문제이다. 코드는 간단하지만 일반화하여 구현하기 위해서는 시간이 필요할 것 같다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
typedef long long ll;
void make_triangle(vector<vector<ll> >&triangle, ll n)
{
ll start = 1;
for(ll i=0; i<n; i++){
for(ll j=0; j<start; j++)
cin >> triangle[i][j];
start++;
}
}
void print_triangle(vector<vector<ll> >&triangle, ll n)
{
ll start = 1;
for(ll i=0; i<n; i++){
for(ll j=0; j<start; j++)
cout << triangle[i][j];
cout << "\n";
start++;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
ll n = 0;
cin >> n;
vector<vector<ll> >triangle(n, vector<ll>(n, 0));
vector<vector<ll> >dp(n, vector<ll>(n, 0));
make_triangle(triangle, n);
// print_triangle(triangle, n);
dp[0][0] = triangle[0][0];
for(ll i=1; i<n; i++){
for(ll j=0; j<=i; j++){
if(j==0)
dp[i][j] = max(dp[i][j], dp[i-1][j] + triangle[i][j]);
else
dp[i][j] = max(dp[i-1][j]+ triangle[i][j] , dp[i-1][j-1]+ triangle[i][j]);
}
}
ll max = dp[0][0];
for(ll i=0; i<n; i++){
for(ll j=0; j<n; j++){
if(max < dp[i][j])
max = dp[i][j];
}
}
cout << max << "\n";
return 0;
}
———————-
백준_실버_2
1.백준(1260) DFS와 BFS
깊이우선탐색(DFS) 와 너비우선탐색(BFS)를 구현하는 문제이며 Graph에서 가장 기본적인 탐색 방법이다.
주의 : STL함수를 사용함에 있어서 call by reference를 사용해야 메모리 초과를 피할 수 있다.
- 문제에서 주어진 조건으로 그래프의 간선들을 서로 연결해준다
- 이어진 간선들의 정점은 오름차순으로 정렬해야 함
- 이미 방문이 끝난 노드들은 재방문을 방지하기 위하여 방문여부를 확인할 수 있는 배열 생성
- 최초 시작 정점을 기준으로 탐색시작
- DFS는 스택을 이용하여 구현
- 최초 출발정점을 스택에 넣은 후 DFS 출발
- 스택의 원소가 하나라도 있다면 다음 반복문 실행
- 스택의 최상단의 원소를 출력 후 pop()하고 해당노드 방문 체크
- 출발 노드의 간선을 모두 탐색하면서 만약 방문이 안된 노드라면 재귀적으로 DFS 호출
- 방문여부 배열 초기화
- BFS는 큐를 이용하여 구현
- 최초 출발정점을 큐에 넣은 후 BFS출발
- 큐의 원소가 하나라도 있다면 다음 반복문 실행
- 현재 노드가 방문기록이 없다면 출력 후 해당 노드 방문체크, pop()
- 출발 노드의 간선을 모두 탐색하면서 방문기록이 없는 노드를 push()
- DFS와는 다르게 모든 간선을 탐색 이후 재귀적으로 BFS를 호출해야한다
- 재귀적으로 BFS호출
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
// 노드의 인접간선들을 연결해주는 함수
void IncidentEdge(vector<int> Graph[], int N)
{
int V1 = 0;
int V2 = 0;
for (int i = 0; i < N; i++)
{
cin >> V1 >> V2;
Graph[V1].push_back(V2);
Graph[V2].push_back(V1);
}
}
// 연결관계를 오름차순으로 정렬
void SortGraph(vector<int> Graph[], int N)
{
for (int i = 1; i <= N; i++)
{
stable_sort(Graph[i].begin(), Graph[i].end());
}
}
// 방문배열 초기화
void init(vector<int> &V, int N)
{
for (int i = 1; i <= N; i++)
V[i] = 0;
}
void print(vector<int> Graph[], int N)
{
for (int i = 1; i <= N; i++)
{
cout << i << "-->";
for (vector<int>::iterator it = Graph[i].begin(); it != Graph[i].end(); it++)
{
cout << *it << "-->";
}
cout << "\n";
}
}
void DFS(vector<int> Graph[], vector<int> &Visit, int Start, stack<int> &S)
{
if (!S.empty()) // 스택의 원소가 하나라도 있다면 실행
{
cout << S.top() << " ";
Visit[Start] = 1;
S.pop(); //출력 이후 방문 체크하고 원소 제거
for (vector<int>::iterator it = Graph[Start].begin(); it != Graph[Start].end(); it++)
{ // 출발 노드의 인접노드 탐색
if (Visit[*it] == 0) //방문기록이 없다면
{
S.push(*it); //해당 원소를 스택에 삽입
DFS(Graph, Visit, *it, S); // 해당 원소를 기준으로 다시 DFS실행
}
}
}
}
void BFS(vector<int> Graph[], vector<int> &Visit, int Start, queue<int> &Q)
{
if (!Q.empty()) //큐의 원소가 하나라도 있다면 실행
{
if (Visit[Start] != 1) //방문기록이 없다면
cout << Q.front() << " "; //출력
Visit[Start] = 1;
Q.pop(); //방문체크 후 제거
for (vector<int>::iterator it = Graph[Start].begin(); it != Graph[Start].end(); it++)
{ //출발 노드의 모든 인접 노드를 탐색
if (Visit[*it] == 0) //방문 기록이 없다면 전부 큐에 삽입
Q.push(*it);
}
BFS(Graph, Visit, Q.front(), Q); //모든 원소를 삽입 한 후 큐의 front를 기준으로 다시 BFS실행
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int Vertical = 0;
int Edge = 0;
int Start = 0;
cin >> Vertical >> Edge >> Start;
//시작 노드의 Index를 1로 고정하기 위해 +1
vector<int> Visit(Vertical + 1, 0);
vector<int> Graph[Vertical + 1];
IncidentEdge(Graph, Edge);
SortGraph(Graph, Vertical);
stack<int> S;
S.push(Start);
DFS(Graph, Visit, Start, S);
cout << "\n";
//// 출발 노드를 스택에 넣어준 후 DFS 실행 ///
init(Visit, Vertical);
queue<int> Q;
Q.push(Start);
BFS(Graph, Visit, Start, Q);
cout << "\n";
//// 출발 노드를 큐에 넣어준 후 BFS 실행 ///
return 0;
}
2.백준(2805) 나무 자르기
이분탐색을 이용하여 간단하게 해결할 수 있는 문제
주의 : int 정수형으로는 표현할 수 없는 수의 범위이다.
- 주어진 나무의 길이 중 가장 긴 나무의 길이를 저장
- 이분탐색 시작
- 가장 긴 나무의 길이의 반을 기준으로 잘라서 확인
- 만약 총합이 더 짧다면 더 길게 잘라야함 오른쪽으로 탐색
- 만약 총합이 더 길다면 더 짧게 잘라야함 왼쪽으로 탐색
- 만약 값이라면 값 리턴
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
long long Num_Tree, Len_Tree = 0;
cin >> Num_Tree >> Len_Tree;
vector<int>Tree(Num_Tree, 0);
long long Max = 0;
for(int i=0; i<Num_Tree; i++){
cin >> Tree[i];
if(Max< Tree[i])
Max = Tree[i];
}
stable_sort(Tree.begin(), Tree.end());
long long Start = 0;
long long End = Max ;
long long Mid = 0;
long long answer = 0;
while(Start <= End){
long long Sum = 0;
Mid =(Start+End)/2;
for(int i=0; i<Num_Tree; i++){
long long temp = Tree[i] - Mid;
if(temp > 0){
Sum += temp;
}
}
if(Sum < Len_Tree)
End = Mid -1;
else{
Start = Mid +1;
if(Mid > answer)
answer = Mid;
}
} //while
cout << answer << "\n";
return 0;
}
3.백준(1654) 랜선 자르기
이분탐색을 이용하여 간단하게 해결할 수 있는 문제
위 문제와 비슷한 형태이다.
주의 : int 정수형으로는 표현할 수 없는 수의 범위이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
ll K = 0;
ll NeedK = 0;
cin >> K >> NeedK;
vector<ll>LAN(K,0);
for(int i=0; i<K; i++)
cin >> LAN[i];
stable_sort(LAN.begin(), LAN.end());
ll low = 1;
ll high = LAN[K-1];
ll mid = 0;
ll ans = 0;
while(low <= high){
mid = (low+high) /2;
ll cnt = 0;
for(int i=0; i<K; i++){
cnt += LAN[i]/mid;
}
if(cnt >= NeedK){
low = mid +1;
if(ans < mid) ans = mid;
}
else{
high = mid -1;
}
}
cout << ans << "\n";
return 0;
}
4.백준(1874) 스택 수열
스택을 이용하여 간다하게 해결 가능
- 주어진 데이터를 받는 배열 선언
- 스택은 오름차순으로 입력되므로 최초 1을 푸쉬
- 스택의 원소가 하나라도 존재한다면 반복
- 만약 스택의 최상단 값과 배열의 값이 같다면 pop()
- 만약 배열의 값이 더 크다면 push()
- 만약 배열의 값이 더 작다면 답이 없음
- return 0;
- 위 정보를 저장한 배열을 출력해주면 끝!
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int testCase = 0;
cin >> testCase;
vector<int>Test(testCase, 0);
stack<int>S;
vector<char> answer;
for(int i=0; i<testCase; i++)
cin >> Test[i];
int idx = 0;
int S_idx = 1;
S.push(S_idx);
answer.push_back('+');
//커맨드 + 쉬프트 + L
while(!S.empty()){
if(S_idx > testCase){
break;
}
int temp = S.top();
if(temp ==Test[idx]){
answer.push_back('-');
S.pop();
idx++;
if(S.empty()){
if(S_idx <testCase)
{
S.push(++S_idx);
answer.push_back('+');
}
}
}
else if(temp<Test[idx]){
S.push(++S_idx);
answer.push_back('+');
}
else{
cout << "NO" <<"\n";
return 0;
}
}
for(auto &ans : answer) cout << ans <<"\n";
return 0;
}
5.백준(18111) 마인크래프트
브르투포스 방법이다… 하지만 생각하기 어려웠다
- 주어진 정보의 MAP을만들고 max값과 min값을 저장
- 최소 시간을 구하는 함수 생성
- 현재 맵을 전부 돌면서
- 현재 땅의 위치보다 레벨이 높다면 (블록을 빼야함)
- 빼고 인벤토리에 저장
- 현재 땅의 위치보다 레벨이 낮다면 (블록을 더해야 함)
- 필요한 블록의 개수를 1개 저장
- 빼고 인벤토리에 저장
- 블록값 계산 - 변화가 없다면 0 리턴 - 블록이 부족한경우 무한대값을 리턴 - 그게 아니라면 걸리는 시간을 리턴
- MAX~MIN까지 반복을 돌면서 최소 시간이 걸리는 레벨과 시간을 찾아준다!
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
#define INF 210000000
using namespace std;
int find_min_time( vector<vector<int> >&map, int level , int N, int M, int B);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N, M, B ;
cin >> N >> M >> B;
int max = 0;
int min = INF;
vector<vector<int> >map(N, vector<int>(M, 0));
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
cin >> map[i][j];
if(map[i][j] >= max)
max = map[i][j];
if(map[i][j] <= min)
min = map[i][j];
}
}
int min_time = INF;
int Level = 0 ;
int time = 0;
for(int i = min; i<= max; i++){
time = find_min_time(map,i,N,M,B);
if(time >=0 && time <= min_time){
min_time = time;
Level = i;
}
}//MAX~MIN
cout << min_time <<" " << Level <<"\n";
return 0;
}
int find_min_time(vector<vector<int> >&map, int level ,int N, int M, int B){
int temp = 0;
int block = 0;
int time = 0;
int neededBlock = 0;
for(int i = 0; i<N; i++){
for(int j=0; j<M; j++){
temp = map[i][j] - level;
if(temp>0){ //만약 temp가 양수라면 현재 level를 기준으로 땅 고르기 했을 때 블록을 빼야함
block = block+temp; //제거는 2초가 걸리며 제거한 블록을 인벤토리에 넣어야 함
// time += 2*temp;
} //if_양수
else if(temp<0){ // 현재 level을 만들기 위해서 블록을 더 올려야 하는경우
neededBlock = neededBlock+abs(temp); //올리기위해 필요한 블록 수를 지정
// time +=abs(temp);
} //if_양수 제외 else
}
}
if(block == 0 && neededBlock ==0){
return 0;
}
if(neededBlock> (B+block)) // 블록이 부족한 경우
return INF;
return block *2 + neededBlock;
}
6.백준(1012) 유기농배추
그래프 탐색 BFS 혹은 DFS를 사용하여 해결하는 문제이다 S1 단지번호붙이기랑 같은 문제이다.
- 주어진 정보에 맞게 배열 생성
- 2중 반복문 순회
- 현재 맵을 전부 돌면서
- 현재 위치에 배추가 있다면
- BFS/DFS 순회 시작
- 스택 또는 큐에 원소가 하나라도 있다면
- 원소를 pop()
- 4방향 탐색
- 배추가 있다면 배추를 제거하고 다시 큐에 삽입 후 탐색
- 연결된 모든 배추를 0으로만들고 카운터 1증가
- 위 결과에서 나온 카운터를 정답 벡터에 푸쉬
- 정답 벡터에 시작부터 끝까지 출력
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;
typedef struct Point{
int X;
int Y;
}Point;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0,-1, 1};
void print(vector<vector<int> >&Farm, int Y, int X);
void Youginong(vector<vector<int> >&Farm, queue<Point>&Q);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int testCase = 0;
cin >> testCase;
vector<int>answer;
while(testCase--){ // TestCase 반복
int Y, X, Num = 0;
cin >> X >> Y >> Num;
vector<vector<int> >Farm(Y, vector<int>(X, 0) );
Point P;
for(int i=0; i<Num; i++){
cin >> P.X >> P.Y;
Farm[P.Y][P.X] = 1;
}
int cnt = 0;
queue<Point>Q;
// 주어진 값에 맞게 입력
for(int i=0; i<Y; i++)
for(int j=0; j<X; j++)
if(Farm[i][j]!=0){
P.X = j;
P.Y = i;
Q.push(P);
Youginong(Farm, Q);
cnt ++;
// 탐색이 끝날 때 마다 카운터 1증가
}
answer.push_back(cnt);
} // Testcase while문
for(vector<int>::iterator it = answer.begin(); it!= answer.end(); it++)
cout << *it << "\n";
return 0;
}
void print(vector<vector<int> >&Farm, int Y, int X){
for(int i=0; i<Y; i++){
for(int j=0; j<X; j++)
cout << Farm[i][j] <<" ";
cout << "\n";
}
}
void Youginong(vector<vector<int> >&Farm, queue<Point>&Q){
if(!Q.empty()){
int Y_size = Farm.size();
int X_size = Farm[0].size();
Point P1;
P1.X = Q.front().X;
P1.Y = Q.front().Y;
Q.pop();
for(int i=0; i<4; i++){
Point P2;
P2.X = P1.X + dx[i];
P2.Y = P1.Y + dy[i];
if( (P2.X >=0 &&P2.X <X_size) && (P2.Y>=0 && P2.Y <Y_size)){
if(Farm[P2.Y][P2.X] == 1){
Farm[P2.Y][P2.X] = 0;
Q.push(P2);
Youginong(Farm, Q);
} // 배추라면
} //범위 내 존재
}
}
}
7.백준(1927) 최소힙
우선순위 큐를 이용하여문제이며 우선순위 큐를 사용할 수 있다면 쉽게 해결이 가능하다.
- 오름차순으로 우선순위 큐 생성
- 주어진 조건에 맞게 연산
- 만약 pop()을 하기전 원소가 없다면 0을 리턴
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
priority_queue<int, vector<int> , greater<int> >pq;
//오름차순 우선순위 큐 새성
int testCase = 0;
cin >> testCase;
while(testCase--){
int Num = 0;
cin >> Num;
if(Num!=0)
pq.push(Num);
//0이 아니라면 푸쉬
else{
if(pq.empty())
cout << 0 <<"\n";
// 0인데 원소가 비어있다면 0 출력
else{
cout << pq.top() <<"\n";
pq.pop();
// 0이면서 원소가 있다면 제일 작은 값 반환
}
}
}
return 0;
}
- 8.백준(11279) 최대힙
우선순위 큐를 이용하여문제이며 위 문제와 같이 우선순위 큐를 사용할 수 있다면 쉽게 해결이 가능하다.
- 내림차순으로 우선순위 큐 생성
- 주어진 조건에 맞게 연산
- 만약 pop()을 하기전 원소가 없다면 0을 리턴
- 자연수가 아니라면 제외
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
priority_queue<int, vector<int> >pq;
int testCase = 0;
cin >> testCase;
while(testCase--){
int Num = 0;
if(Num<0){continue;} // 자연수가 아니라면 제외
cin >> Num;
if(Num!=0)
pq.push(Num);
else{
if(pq.empty())
cout << 0 <<"\n";
else{
cout << pq.top() <<"\n";
pq.pop();
}
}
}
return 0;
}
9.백준(11724) 연결 요소의 개수
그래프에서 연결된 개수를 파악하는 문제이다 유니온파인드 또는 그래프 탐색으로 해결할 수 있다. 다음번에는 유니온파인드를 이용해봐야겠다.
- 주어진 조건에 맞게 연결 그래프 생성
- 그래프 노드를 전부 돌아다니면서 방문 벡터를 확인하면서 DFS탐색 시작
- DFS가 수행된 횟수만큼 횟수 증가
- 횟수 리턴해주면 끝
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
void DFS(vector<int>Graph[], vector<int>&Visit, stack<int>&S){
if(!S.empty()){
int temp = S.top();
S.pop();
Visit[temp] = 1;
for(auto g : Graph[temp]){
if(Visit[g]==0){
S.push(g);
DFS(Graph, Visit, S);
}
}
}
}
// DFS연산
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N, M;
cin >> N >> M ;
vector<int>Graph[N+1];
vector<int>Visit(N+1, 0);
// 재방문을 피하기위한 방문 배열 생성
int A,B;
stack<int>S;
for(int i=0; i<M; i++){
cin >> A >> B;
Graph[A].push_back(B);
Graph[B].push_back(A);
}
// 주어진 조건에 맞게 연결
int cnt = 0;
for(int i=1; i<=N; i++){
if(Visit[i]==0){
// 방문된적이 없다면 연산 시작
S.push(i);
DFS(Graph, Visit,S);
cnt ++;
}
}
cout << cnt << "\n";
return 0;
}
9.백준(2630) 색종이
재귀를 이용하여 푸는 문제이며 무식하게 풀기는 했다.. 쿼드쿼리?를 이용해서도 풀 수 있는것 같다.
- 정사각형 정보 입력
- 현재 정사각형이 모두 같지 않다면 0을 리턴
- 만약 정사각형이 모두 같지 않다면 4개의 벡터를 이용하여 4등분
- 만약 정사각형이 모두 같다면 그 안에 색에 따라 색종이 색 증가.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int Blue;
int White;
void print(vector<vector<int> >&Map, int N){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
cout << Map[i][j] <<" ";
}
cout <<"\n";
}
} //확인용
bool findMap(vector<vector<int> >&Map){
if(Map.size()==1){return true;}
int check = Map[0][0];
for(int i=0; i<Map.size(); i++){
for(int j=0; j<Map[i].size(); j++){
if(check != Map[i][j]){return false;}
}
}
return true;
} //모두 정사각형이 같은 색이면 1 아니면 0
void makeMap(vector<vector<int> >&Map){
if(findMap(Map)!=1){
int SZ = Map.size()/2;
// 정사각형이므로 size/2만 해준다.
vector<vector<int> >New_A(SZ, vector<int>(SZ, 0));
vector<vector<int> >New_B(SZ, vector<int>(SZ, 0));
vector<vector<int> >New_C(SZ, vector<int>(SZ, 0));
vector<vector<int> >New_D(SZ, vector<int>(SZ, 0));
//4등분 하므로 4개의 벡터 생성
for(int i=0; i<SZ; i++){
for(int j=0; j<SZ; j++){
New_A[i][j] = Map[i][j];
}
} //1
int x = 0;
int y = 0;
for(int i=0; i<SZ; i++){
x = 0;
for(int j=SZ; j<Map.size(); j++){
New_B[i][x++] = Map[i][j];
}
} //2
for(int i=SZ; i<Map.size(); i++){
for(int j=0; j<SZ; j++){
New_C[y][j] = Map[i][j];
}
y++;
}//3
x = 0;
y = 0;
for(int i=SZ; i<Map.size(); i++){
x = 0;
for(int j=SZ; j<Map.size(); j++){
New_D[y][x++] = Map[i][j];
}
y++;
}
// 4등분한 정사각형 벡터에 각각의 값들을 삽입
makeMap(New_A);
makeMap(New_B);
makeMap(New_C);
makeMap(New_D);
// 4등분한 정사각형을 다시 찾음
} //if
else{
if(Map[0][0] ==1){Blue++;}
else{White++;}
// 만약에 같은 색으로 나눠졌다면
// 1이면 파란색이므로 파란색 1추가
// 0이면 하얀색이므로 하얀색 1추가
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
vector<vector<int> >Map(N, vector<int>(N,0));
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
cin >> Map[i][j];
makeMap(Map);
cout << White <<"\n" << Blue ;
return 0;
}
10.백준(18870) 좌표압축
문제 자체는 어렵지 않다 하지만 이번 문제에서는 이진탐색을 사용하지 않는다면 시간초과를 피할 수 없다. 이진탐색 STL을 활용하면 쉽게 해결이 가능하다 binary_search 함수와 중복제거 함수를 배울 수 있는 좋은 기회였다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
vector<int>V(N,0);
for(int i=0; i<N; i++){
cin >> V[i];
}
vector<int>Sorted_V;
Sorted_V = V;
sort(Sorted_V.begin(), Sorted_V.end()); // 이진탐색을 위해 정렬
Sorted_V.erase(unique(Sorted_V.begin(), Sorted_V.end()), Sorted_V.end()); // 중복값 제거
for(int i=0; i<N; i++){
int compare = V[i];
cout << lower_bound(Sorted_V.begin(), Sorted_V.end(), compare) - Sorted_V.begin() << " ";
// lower_bound는 찾는값이 가장 먼저 나온 인덱스값을 반환해준다.
}
return 0;
}
11.백준(11742) 연결 요소의 개수
그래프에서 연결된 개수를 파악하는 문제이다 유니온파인드 또는 그래프 탐색으로 해결할 수 있다. 다음번에는 유니온파인드를 이용해봐야겠다.
- 주어진 조건에 맞게 연결 그래프 생성
- 그래프 노드를 전부 돌아다니면서 방문 벡터를 확인하면서 DFS탐색 시작
- DFS가 수행된 횟수만큼 횟수 증가
- 횟수 리턴해주면 끝
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
void DFS(vector<int>Graph[], vector<int>&Visit, stack<int>&S){
if(!S.empty()){
int temp = S.top();
S.pop();
Visit[temp] = 1;
for(auto g : Graph[temp]){
if(Visit[g]==0){
S.push(g);
DFS(Graph, Visit, S);
}
}
}
}
// DFS연산
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N, M;
cin >> N >> M ;
vector<int>Graph[N+1];
vector<int>Visit(N+1, 0);
// 재방문을 피하기위한 방문 배열 생성
int A,B;
stack<int>S;
for(int i=0; i<M; i++){
cin >> A >> B;
Graph[A].push_back(B);
Graph[B].push_back(A);
}
// 주어진 조건에 맞게 연결
int cnt = 0;
for(int i=1; i<=N; i++){
if(Visit[i]==0){
// 방문된적이 없다면 연산 시작
S.push(i);
DFS(Graph, Visit,S);
cnt ++;
}
}
cout << cnt << "\n";
return 0;
}
12.백준(1912) 연속합
구간에 연속합을 구하는 문제이며 여러 알고리즘 중에서 Kadane 알고리즘을 사용하면 O(n)의 시간복잡도로 해결이 가능하다.
- 주어진 배열을 순차적으로 탐색
- 만약 구간의 합이 음수라면 도움이 안되므로 그 구간은 버림
- 최대 값의 구간을 저장
#include <iostream>
#include <vector>
#define MAX_SIZE -2100000000
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int size = 0;
cin >> size ;
int minMax = MAX_SIZE;
vector<int>V(size, 0);
bool check = false;
for(int i=0; i<size; i++){
int temp = 0;
cin >> temp;
if(temp>0)
check = true;
else{
if(minMax<temp)
minMax = temp;
}
V[i] = temp;
}
int sum = 0;
int startIdx = 0;
int endIdx = 0;
int cnt = -1;
int max = V[0];
if(check == false){
cout << minMax <<"\n";
}
else{
for(int i=0; i<size; i++){
sum += V[i];
cnt ++;
if(sum<=0){
sum = 0;
cnt = -1;
}
else{
if(max<=sum){
startIdx = i-cnt;
max = sum;
endIdx = i;
}
}
}
cout << max <<"\n";
}
return 0;
}
13.백준(4963) 섬의 개수
BFS를 이용하면 쉽게 해결할 수 있는 문제이다.
- 주어진 조건에 맞게 map,visit 배열 생성
- 전체 맵을 돌면서 연결된 섬의 개수를 BFS를 통해 확인
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef struct Point{
int x;
int y;
}point;
int dx[8] = {0,1,-1,0,1,1,-1,-1};
int dy[8] = {1,0,0,-1,-1,1,1,-1};
void Init(vector<vector<int> >&map, int x, int y);
void CheckVector(vector<vector<int> >&V, int x, int y);
void BFS(vector<vector<int> >&map,vector<vector<int> >&visit, queue<point>&q);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin);
//1 Land
//0 Sea
int x = 0;
int y = 0;
cin >> x >> y ;
while(x!=0 && y!=0){
vector<vector<int> >map(y,vector<int>(x,0));
vector<vector<int> >visit(y,vector<int>(x,0));
queue<point>q;
point p;
Init(map,x,y);
int cnt = 0;
for(int i=0; i<y; i++){
for(int j=0; j<x; j++){
if(visit[i][j]==0 && map[i][j] ==1){
p.x = j;
p.y = i;
visit[p.y][p.x] = 1;
q.push(p);
BFS(map,visit,q);
cnt++;
}
}
}
cout << cnt <<"\n";
cin >> x >> y ;
}
return 0;
}
void Init(vector<vector<int> >&map, int x, int y){
for(int i=0; i<y; i++){
for(int j=0; j<x; j++){
cin >> map[i][j];
}
}
}
void CheckVector(vector<vector<int> >&V, int x, int y){
for(int i=0; i<y; i++){
for(int j=0; j<x; j++){
cout << V[i][j] <<" ";
}
cout << "\n";
}
}
void BFS(vector<vector<int> >&map,vector<vector<int> >&visit, queue<point>&q){
if(!q.empty()){
int x = map[0].size();
int y = map.size();
point p;
p.x = q.front().x;
p.y = q.front().y;
q.pop();
for(int i=0; i<8; i++){
point P;
P.x = dx[i] + p.x;
P.y = dy[i] + p.y;
if((P.x>=0 && P.x<x) && (P.y>=0 && P.y<y)){
if(visit[P.y][P.x]==0 && map[P.y][P.x] ==1){
visit[P.y][P.x] = 1;
q.push(P);
}
}
}
BFS(map,visit,q);
}
}
14.백준(2553) 마지막 팩토리얼 수
단순 구현
- 정수형 범위를 벗어나지 않게 하기위해 중간중간 나머지를 계산한다.
// 백준 정리 필요
#include <iostream>
using namespace std;
typedef long long ll;
ll factorial(int N, int count);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int number = 0;
cin >> number ;
cout << factorial(1,number) % 10 <<"\n";
return 0;
}
ll factorial(int count, int N){
if(N <= 1) return count;
count = count*N;
while(count%10 == 0) count/=10;
count = count%100000;
return factorial(count, N-1);
}
———————-
백준_실버_3
1. 백준(1003)피보나치 함수
풀이
위 문제는 단순히 0과1이 나온 횟수를 구하는 문제가 아닌 메모제이션을 이용하여 반복적인 계산을 피해 시간초과가 나지않게 하는것이 주 목적이다.</h4>
- 피보나치 함수를 재귀적으로 사용하지만 동일한 계산을 할 때 효율적인 메모제이션 방식을 이용하여 이미 계산된 피보나치 수열의 값을 저장하는 방식으로 시간초과 해결
- 0이 나온횟수와 1이 나온횟수의 패턴을 분석한 결과
- 1이 나온횟수 = fib(n)의 값과 동일
- 0이 나온횟수 = fib(n-1)의 값과 동일
위와 같은 패턴이 나온다는걸 확인
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<long long>ans(100,0); //이미 계산된 값을 저장하기 위한 벡터
int fib(int N){
if(N<=1)
return N;
else{
int idx = N-2;
if(ans[idx]!=0){ //만약 이미 값이 저장되어있다면 그 값을 반환
return ans[idx];
}
else{ // 값이 저장되어 있지않다면 값을 저장
ans[idx] = fib(N-2) + fib(N-1);
return ans[idx];
}
}
}
int main(){
int testCase = 0;
cin >> testCase;
while(testCase--){
int N =0 ;
cin >>N;
int zero = 0;
int one = 0;
if(N==0){
zero = 1;
}
else if(N==1){
one = 1;
}
else{
one = fib(N); //1이 나온횟수
zero = fib(N-1); //0이 나온횟수
}
cout <<zero << " ";
cout << one << "\n";
}
return 0;
}
2.백준(1929) 소수 구하기
일반적인 소수를 구하는 방법이 아닌 에라토스테네스의 체를 이용하는 방법으로 푸는 문제이다
- i = 2 ~ i*i<N 까지 반복문을 돌린다 그 이유는 어차피 배수이기때문에 원하는 의 루트값까지만 가도 이미 모든 소수는 구해진다
- j = 2*i ~ j<=N 까지 j=j+i 즉 주어진값의 배수만큼 반복을 돌아준다
- 미리 선언했던 배열의 모든 값을 0으로 바꾼 후 만약 현재 값이 제거 되지않았다면 그 배수부터 제거 하는 방식으로 처리한다
- 에라토스테네스의 체는 소수를 한번에 찾거나 개수 등을 찾을 때 유용하다
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void PrimeNum(int M, int N)
{
vector<int>Prime(1000001, 0);
Prime[0] = 1;
Prime[1] = 1;
for(int i=2; i*i<1000001; i++)
for(int j=2*i; j<1000001; j=j+i)
if(Prime[i] == 0)
Prime[j] =1;
for(int i=M; i<=N; i++)
if(Prime[i]==0)
cout << i << "\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int M, N;
cin >> M >> N;
PrimeNum(M,N);
return 0;
}
3.백준(1463) 1로 만들기
다이나믹 프로그래밍을 이용하여 푸는 문제이다. 한 번 계산된 값을 테이블에 저장하야 재연산하는 과정을 피하는 방법이다. 만약 배열의 값이 저장되어있지 않다면 새롭게 갱신한다.
- 3으로 나뉘어지면서 2로 나뉘어지는경우
- 3으로 나뉘어진 값과 2로 나뉘어진 값 중 최소값을 찾는다
- 그 최소값과 N-1을 한 값중 최솟값을 찾아 그 값을 배열의 갱신해준다. 이 과정이 필요한가 ?
- 3으로만 나뉘어지는경우
- 3으로 나뉘어진 값과 N-1을 한 값중 최솟값을 찾아 그 값을 배열의 갱신해준다.
- 2으로 나눠지는 경우
- 2로 나뉘어진 값과 N-1값 중 최솟값을 찾아 그 값을 배열의 갱신
- 둘 다 아닌경우
- N-1의 값을 배열의 갱신
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>ONE(1000001,0);
int makeOne(int N){
if(N<=3)
return ONE[N];
else{
if(N%3==0){
if(ONE[N]==0){ // 처음 계산되는 상황
if(N%2==0){
int min = makeOne(N/3)<makeOne(N/2)?ONE[N/3]:ONE[N/2];
ONE[N] = min<makeOne(N-1)?(min+1):(1+ONE[N-1]);
return ONE[N];
}//3,2로 나눠지는경우
else{
ONE[N] = makeOne(N/3)<makeOne(N-1)?(1+ONE[N/3]):(1+ONE[N-1]);
return ONE[N];
}//3으로만 나눠지는경우
}
else
return ONE[N];
}//3으로 나눠지는 경우
if(N%2==0){
if(ONE[N]==0){
ONE[N] = makeOne(N/2)<makeOne(N-1)?(1+ONE[N/2]):(1+ONE[N-1]);
return ONE[N];
}
else
return ONE[N];
} //2로 나눠지는 경우
else{
if(ONE[N]==0){ // 둘 다 아닌경우
ONE[N] = 1+makeOne(N-1);
return ONE[N];
}
else
return ONE[N];
}
}//else
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
ONE[0] = 0;
ONE[1] = 0;
ONE[2] = 1;
ONE[3] = 1;
int N = 0;
cin >> N ;
int ans = makeOne(N);
cout << ans << "\n";
return 0;
}
4.백준(11399) ATM
단순하게 주어진 값을 정렬 한 뒤 필요한 시간을 더해주기만 하면 끝나는 문제로 난이도가 상당히 낮았다.
- 단순하게 주어진 값을 정렬한 후 최소 대기줄부터 계산
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N = 0;
cin >> N;
vector<int>ans(N,0);
for(int i=0 ;i<N; i++)
cin >> ans[i];
stable_sort(ans.begin(), ans.end());
int answer = 0;
for(int i=1; i<N; i++)
ans[i] = ans[i] + ans[i-1];
for(int i=0; i<N; i++)
answer += ans[i];
cout << answer << "\n";
return 0;
}
5.백준(11047) 동전
그리디 알고리즘에 대표적인 문제로 최소동전으로 원하는 동전의 합을 만드는 방법이다.
- 그리디 알고리즘 문제이므로 별다른 방법이 존재하지않고 현재 상황에 가장 최선의 해를 찾아주기만 하면 쉽게 풀린다.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N = 0;
int target_M = 0;
cin >> N >> target_M;
int min_coins = 0;
vector<int>coins(N,0);
for(int i=0; i<N; i++)
cin >> coins[i];
for(int i=N-1; i>=0; i--){
if(target_M>=coins[i]){
min_coins += target_M/coins[i];
target_M = target_M %coins[i];
}
}
cout << min_coins << "\n";
return 0;
}
6.백준(9095) 1,2,3 더하기
다이나믹 프로그래밍을 이용하여 해당 정수를 1,2,3의 합으로 나타내는 문제이다.
- 처음 1,2,3 테이블을 기준으로 동적프로그래밍 기법을 사용하여 테이블을 갱신하는 방법으로 풀면 간단하게 풀 수 있다.
- 4는 결국 3번 테이블의 경우의 수 + 2번 테이블의 경우의 수 + 1번 테이블의 경우의 수이다
- 일반화 : N번은 결국 N-1테이블 + N-2테이블 + N-3테이블로 표현할 수 있다.
#include <iostream>
using namespace std;
// 문제에서 N은 11보다 작으므로 해당 테이블 생성
int DP[12];
int getDP(int N){
// 해당 테이블의 값이 있다면 그 값을 리턴
if(DP[N]!=0)
return DP[N];
else{
// 해당 테이블의 값이 없다면 1,2,3 테이블을 이용하여 갱신 후 반환
DP[N] = getDP(N-1) + getDP(N-2) + getDP(N-3);
return DP[N];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// 초기 1,2,3 테이블 갱신
DP[0] = 0;
DP[1] = 1;
DP[2] = 2;
DP[3] = 4;
int testCase = 0;
cin >> testCase ;
while(testCase--){
int Num = 0;
cin >> Num;
int answer = getDP(Num);
cout << answer << "\n";
}
return 0;
}
7.백준(1966) 프린터 큐
큐와 우선순위 큐 두가지를 이용하여 해결하면 쉽게 해결할 수 있는 문제였다 하지만 나에게는 생소한 접근방법이라 어려웠다….
- 문서에 중요도와 인덱스를 저장하는 큐와 문서의 중요도를 우선순위로 저장하는 우선순위 큐 두 개를 생성
- 주어진 조건에 맞게 큐{인덱스, 중요도}삽입 , 우선순위 큐에는 {중요도}만을 삽입
- 큐의 원소가 하나라도 있다면 반복 실행
- 현재 큐에 저장된 인덱스와 중요도를 가져온 뒤 제거
- 가져온 중요도와 우선순위큐에 저장된 중요도(가장높은 순서)가 같다면 카운터를 1증가
- 중요도와 인덱스 모두 같다면 그 문서가 찾는 문서이므로 카운터 출력 후 break
- 중요도가 같지않다면 큐에서 빼온 원소를 다시 큐에 제일 마지막에 삽입
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef struct Document{
int Num; //문서의 인덱스
int imp; //문서의 중요도
}Document;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int testCase = 0;
cin >> testCase;
while(testCase--){
Document Docu;
queue<Document>q;
// 문서에대한 정보를 저장하는 큐
priority_queue<int>pq;
// 문서의 중요도를 저장하는 우선순위 큐
int cnt = 0;
int D,T,I = 0;
cin >> D >> T;
// 문서의 개수와 목표 문서의 인덱스를 입력받음
for(int i=0; i<D; i++){
cin >> Docu.imp ;
// 문서의 중요도를 입력받아서 구조체에 삽입
Docu.Num = i;
q.push(Docu); // 문서의 번호와 중요도를 저장
pq.push(Docu.imp); //중요도를 우선순위 정렬
}
while(!q.empty()){ //Queue의 원소가 하나라도 있다면 반복
int comT = q.front().Num;
int comI = q.front().imp;
q.pop();
// Target인덱스와 중요도 비교를 위해 Queue의 저장된 원소들을 각각 가져오고 제거
if(pq.top() == comI){ // Queue에 저장된 문서의 중요도와 우선순위 큐에 저장된 중요도를 비교했을때 같은경우
// Queue -> [{0,1}, {1,1}, {2,9}, {3,1}, {4,1}, {5,1} ]
// Pri_Q -> [9, 1, 1, 1, 1, 1 ]
// 가장 높은 우선순위(중요도)가 높은 문서는 우선순위 큐에 제일 앞에 위치하고 있다
// 결국 가장 중요도가 높은 문서가 나오기 전까지 Queue의 원소는 계속 뒤로 붙고 그게 아니라면 중요도가 높은 순서대로 하나씩 빼주면서 개수를 올려주면 된다.
pq.pop();
cnt++;
if(comT == T){ // 현재 비교하는 인덱스가 Target인덱스인경우 즉 원하는 문서의 위치를 찾은 경우
cout << cnt << "\n";
break;
}
}
else{ // 만약 중요도가 다르다면 현재 꺼낸 원소들을 다시 큐의 맨 뒤로 보내기
Docu.Num = comT;
Docu.imp = comI;
q.push(Docu);
}
}
}//while
return 0;
}
8.백준(2108) 통계학
최빈값을 제외하고는 단순하게 풀 수 있는 문제였다… 인덱스를 잘 설정해야한다…
배열의 인덱스는 양수만 접근이 가능하다 음수가 나왔을 경우 처리하는 방법에 대해 알 수 있었다.
먼저 오름차순으로 배열 정렬
- 산술평균
- float 보다 double 자료형이 더 정확하다!
- 중간값
- 단순하게 정렬된 배열의 중간값 반환
- 최빈값
- 절대값이 4000은 넘지 않음
- 빈도수와 인덱스를 저장이 필요하므로 구조체 벡터 생성
- 반복을 돌면서 빈도수 계산
- 만약 최빈값이 중복이라면 2번째로 작은 수를 출력해야므로 정렬기준을 새롭게 정의
- 절대값이 4000은 넘지 않음
- 범위
- 배열의 처음과 끝의 차이를 반환
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
void fun1(vector<int>&A, int size);
void fun2(vector<int>&A, int size);
void fun3(vector<int>&A, int size);
void fun4(vector<int>&A, int size);
typedef struct Dic
{
int Cnt;
int Num;
}Dic;
vector<Dic>V(500001);
bool com(const Dic &a, const Dic &b){
if (a.Cnt > b.Cnt)
return true;
else if(a.Cnt == b.Cnt)
return a.Num <= b.Num;
return false;
}
int main(){
// freopen("input.txt", "r", stdin);
int testCase = 0;
scanf("%d", &testCase);
vector<int>A(testCase, 0);
for(int i=0; i<testCase; i++)
scanf("%d", &A[i]);
stable_sort(A.begin(), A.end());
fun1(A,testCase);
fun2(A,testCase);
fun3(A,testCase);
fun4(A,testCase);
return 0;
}
void fun1(vector<int>&A, int size){ //산술평균
double mean = 0; // float 보다 double이 정확도가 높다..
for(int i=0; i<size; i++)
mean += A[i];
if(round(mean/size) == -0){
cout << 0 <<"\n";
}
else
cout << round(mean/size) <<"\n";
}
void fun2(vector<int>&A, int size){ // 중간값
int mid = size/2;
printf("%d\n", A[mid]);
}
void fun3(vector<int>&A, int size){ //최빈값
for(int i=0; i<size; i++){
if(A[i]<0){ //음수인경우
int temp = 4000 - A[i];
V[temp].Cnt += 1; // 빈도수
V[temp].Num = A[i]; // 인덱스
}
else{
V[A[i]].Cnt += 1; //빈도 수
V[A[i]].Num = A[i];// 인덱스
}
}
stable_sort(V.begin(), V.end(), com); // 가장 많이 나온 순서로 정렬 만약 같다면 인덱스값을 오름차순으로 정렬
if(V[0].Cnt != V[1].Cnt)
cout << V[0].Num <<"\n"; // 만약 최빈값이 중복이 없다면 바로 출력
else
cout << V[1].Num <<"\n"; //중복이 있다면 2번째로 작은 수 출력
}
void fun4(vector<int>&A, int size){
int max = *max_element(A.begin(), A.end());
int min = *min_element(A.begin(), A.end());
int answer = max-min;
cout << answer <<"\n";
}
9.백준(2606) 바이러스
그래프 탐색 문제이다 DFS 또는 BFS를 이용하여 해결이 가능하다
주의 : 함수를 쓸 때 call by reference를 사용해야 메모리 초과와 시간초과를 피할 수 있다.
DFS로 구현
- 주어진 조건에 맞게 그래프 생성
- 감염여부를 저장할 배열 생성
- DFS 탐색 시작
- 탐색을 하면서 갯수를 한개씩 증가
- 최초 1번 컴퓨터는 횟수에 포함되지않으므로 1개를 빼준다
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
void DFS(vector<int>Graph[], vector<int> &Virus, stack<int> &S, int Start, int &cnt);
void Print(vector<int>Grpah[], int N);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int numOfcumputer = 0;
int numOfEdge = 0;
cin >> numOfcumputer >> numOfEdge ;
vector<int>Graph[numOfcumputer+1]; //0 버림
vector<int>Virus(numOfcumputer+1, 0);
for(int i=0; i<numOfEdge; i++){
int A,B = 0;
cin >> A >> B;
Graph[A].push_back(B);
Graph[B].push_back(A);
}
for(int i=1; i<numOfcumputer; i++)
stable_sort(Graph[i].begin(), Graph[i].end());
stack<int>S;
S.push(1);
int cnt = 0 ;
DFS(Graph,Virus, S,1,cnt) ;
cout << cnt-1 << "\n";
// Print(Graph, numOfcumputer);
return 0;
}
void DFS(vector<int>Graph[],vector<int> &Virus, stack<int> &S, int Start, int &cnt){
if(!S.empty()){
cnt++;
Virus[Start] = 1;
S.pop();
for(vector<int>::iterator it = Graph[Start].begin(); it != Graph[Start].end(); it++){
if(Virus[*it] == 0){ //바이러스 감염이 안된경우
S.push(*it);
// cout << "Cnt is " << cnt << " " << "index is " << *it << "\n";
DFS(Graph, Virus, S, *it, cnt);
}
}
}
}
void Print(vector<int>Grpah[], int N){
for(int i=1; i<=N; i++){
cout << i << ": ";
for(vector<int>::iterator it = Grpah[i].begin(); it != Grpah[i].end(); it++)
cout << *it << "--->";
cout << "\n";
}
}
10.백준(11726) 2xn 타일링
다이나믹 프로그래밍 문제이며 메모제이션을 이용한다
주의 : 큰 수를 계산할 때 오버플로우가 날 수 있으므로 최종 단계가 아닌 계산 도중 다이나믹 테이블에 값을 넣을 때 % 10007을 해줘야 한다.
DP로 구현
- 0,1,2값 을 미리 배열에 삽입
- 타일링 패턴을 보면 결국 DP[N] = DP[N-1] + DP[N-2]의 구조를 가지고 있으므로 해당 식에 맞게 계산
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>DP(1001, 0);
int Tileing(int N);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
DP[1] = 1%10007;
DP[2] = 2%10007;
int answer = Tileing(N);
cout << answer << "\n";
return 0;
}
int Tileing(int N){
if(DP[N]!=0)
return DP[N]%10007;
else{
DP[N] = (Tileing(N-1)) + (Tileing(N-2));
return DP[N]%10007;
}
}
- 11.백준(2579) 계단오르기
다이나믹 프로그래밍 문제이며 메모제이션을 이용한다
주의 : 패턴을 파악하면 쉬운 문제인데 ... 파악하기까지 오래 걸렸음...
DP로 구현
- 0,1,2,3의 경우 최대 값을 미리계산 N=5라고 가정한다면
- 최초 DP에 저장된 N-2의 값과 자기 자신을 더함 3칸이상 연속될 수 없다는 조건이 있으므로 DP[N-2]의 값은 연속되지 않은 2칸이전의 최대값임
- 반복문을 돌면서 DP[N-3] + N-2 + N .. 이런식으로 더해가며 최대값을 갱신한다
- 최대값 테이블을 갱신하고 리턴해주면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
vector<int>DP(301,0);
int Climbing_Stairs(vector<int> &Score, int N);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" , stdin);
int N = 0;
cin >> N;
vector<int>Score(N+1,0);
for(int i=1; i<=N; i++)
cin >> Score[i];
DP[1] = Score[1];
DP[2] = DP[1]+Score[2];
DP[3] = max(Score[1], Score[2]) + Score[3];
// 최초 3개의 DP테이블 셋팅
int answer = Climbing_Stairs(Score, N);
cout << answer << "\n";
return 0;
}
int Climbing_Stairs(vector<int> &Score, int N){
if(DP[N] !=0 ){
return DP[N];
}// 이미 값이 있다면 값을 리턴
else{
int MAX = Climbing_Stairs(Score, N-2)+Score[N]; // 최초 값을 저장
for(int i =N-3; i>0; i--){
int t_m = Climbing_Stairs(Score, i) + Score[N]; // 자신 + DP[N-3]의 값을 저장
int temp = i+2; // 2칸씩 증가함
while(temp<N){
t_m = t_m+ Score[temp]; // 2칸 전 값을 저장
temp = temp +2;
}
MAX = max(MAX, t_m); //최대값 갱신
}
DP[N] = MAX; //최대값 테이블에 저장
return DP[N];
}
}
12.백준(9461) 파도반 수열
다이나믹 프로그래밍 문제이며 메모제이션을 이용한다
패턴만 파악하면 쉽게 해결가능 단 자료형을 주의하자! 항상 제일 마지막 케이스를 넣어봐서 오버플로우를 확인하는 습관 필요
DP로 구현
- 0,1,2,3,4,5의 경우 값을 미리 계산 N=5라고 가정한다면
- DP[N] = DP[N-4] + DP[N-5] 패턴으로 리턴해주면 간단하게 해결가능하다
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
ll DP[101];
// 오버플로우 방지
ll P(int N);
// 오버플로우 방지
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
DP[0] = 0;
DP[1] = 1;
DP[2] = 1;
DP[3] = 1;
DP[4] = 2;
DP[5] = 2;
// 5번까지 미리 삽입
int testCase = 0;
cin >> testCase ;
while(testCase--){
int N = 0;
cin >> N;
cout << P(N) <<"\n";
}// while
return 0;
}
ll P(int N){
if(DP[N]!=0){
return DP[N];
}
else{
DP[N] = P(N-1) + P(N-5);
// DP[N] = DP[N-1] + DP[N-5]의 패턴
return DP[N];
}
}
13.백준(11727) 2×n 타일링2
다이나믹 프로그래밍 문제이다 수식을 찾기만 하면 쉽게 해결이 가능하다.
패턴만 파악하면 쉽게 해결가능하다. int정수형을 벗어나므로 10007을 나머지 연산을 이용한다.
DP로 구현
- 0,1,2,3의 경우는 미리계산 N=5라고 가정한다면
- DP[N] = DP[N-1] + DP[N-2]*2 패턴이므로 재귀적으로 수식을 만들어주면 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>DP(1001,0);
int Tileing(int N);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
DP[0] = 0;
DP[1] = 1;
DP[2] = 3;
DP[3] = 5;
int answer = Tileing(N);
cout << answer << "\n";
return 0;
}
int Tileing(int N){
if(DP[N]!=0){
return DP[N];
}
else{
DP[N] = ( (Tileing(N-1) + Tileing(N-2)*2 )) % 10007;
return DP[N];
}
}
- 14.백준(9375) 패션왕 신해빈
Map(Key,Value) 라이브러리를 이용하여 해결할 수 있는 문제이다.
Map을 사용하는게 어려운게 아니라 수학 수식을 세우는게 조금 어려웠던 문제이다.
- 조건에 맞게 Key Value 형식으로 추가
- 옷을 하나만 입는것도 포함되므로 입을 수 있는 옷의 종류 +1
- (a+1) * (b+1)의 수식을 세울 수 있음
- 옷을 아예 입지 않는경우는 제외하므로 최종 결과에서 -1
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int testCase = 0;
cin >> testCase;
while(testCase--){
int Num = 0;
cin >> Num;
string Clothes;
string Class;
map<string, int>M;
for(int i=0; i<Num; i++){
cin >> Clothes >> Class;
if(M.count(Class)==0){
M.insert(make_pair(Class,1));
}
else{
M.insert(make_pair(Class,M[Class]++));
}
}
int answer = 1;
for(auto m : M){
answer *= m.second+1;
//(a+1)*(b+1)*(c+1)....
}
answer --;
// 옷을 아예 입지 않는 경우는 제외
cout << answer << "\n";
}
return 0;
}
15.백준(11659) 구간 합 구하기 4
입력을 받으면서 미리 구간합의 합을 배열에 저장하는 방식으로 푸는 문제이다.
일반적으로 입력을 받고 배열을 순회한다면 시간초과를 피할 수 없다. 미리 구간 누적을 계산해 놔야한다.
- 주어진 조건보다 크기가 1 더 큰 배열 생성
- 입력은 받으면서 현재 누적된 값 + 입력된 값을 배열에 삽입
- 이미 배열에는 해당하는 인덱스까지 구간 합이 다 구해져있으므로 B-A(-1)값을 반환
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N,M =0;
cin >> N >> M;
vector<int>V(N+1,0);
for(int i=1; i<=N; i++){
int temp = 0;
cin >> temp ;
V[i] = V[i-1]+temp; //이전값과 함께 저장
}
for(int i=0; i<M; i++){
int A, B;
cin >> A >> B;
cout << V[B]-V[A-1] <<"\n";
}
return 0;
}
16.백준(4948) 베르트랑 공준
에라스토테네스의 체를 이용하여 해결하는 문제이다 N의 크기가 그렇게 크지않은경우는 에라토스테네스의 체를 이용하면 시간초과를 피할 수 있다.
이 때 주어진 조건에 맞는 크기의 루트를 씌운 값만큼만 반복을 돌려도 모든 소수를 구할 수 있다.
- 주어진 조건에 맞게 벡터 생성
- i=2 -> sqrt(SIZE) 만큼 반복을 하며 에라토스테네스 벡터 갱신
- 주어진 입력값에 맞게 카운터를 체크한 후 출력
#include <iostream>
#include <vector>
#include <cmath>
#define SIZE (123456*2) +1
using namespace std;
vector<int>PrimeNumber(SIZE, 0);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
PrimeNumber[0] = 1;
PrimeNumber[1] = 1;
int size = sqrt(SIZE); // 주어진 사이즈의 루트만큼만 반복문을 돌아도 충분하다.
for(int i=2; i<=size; i++){
if(PrimeNumber[i] ==0){
for(int j=i*2; j<=SIZE; j =j+i){
PrimeNumber[j] = 1;
}
}
}
int N=0;
cin >> N;
while(N!=0){
int cnt = 0;
for(int i=N+1; i<=2*N; i++){
if(PrimeNumber[i]==0)
cnt++;
}
cout << cnt << "\n";
cin >> N;
}
return 0;
}
17.백준(1735) 분수 합
최소공배수를 구하는 유클리드 호제법을 사용하면 쉽게 해결이 가능하다.
- 주어진 조건에 맞게 변수에 분수 값 대입
- 유클리드 호제법을 이용하여 값을 구함
- 분모와 분자를 2번에서 얻은 값으로 나눠 줌
#include <iostream>
using namespace std;
int gcd(int a, int b);
void fractionAdd(int a, int b, int c, int d);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int a = 0;
int b = 0;
int c = 0;
int d = 0;
cin >> a >> b >> c >> d;
fractionAdd(a,b,c,d);
return 0;
}
int gcd(int a, int b){
if(b==0)
return a;
else
return gcd(b, a%b);
}
void fractionAdd(int a, int b, int c, int d){
int answerA = 0;
int answerB = 0;
if(b!=d){
answerB = b*d;
answerA = (a*d) + (b*c);
}
else{
answerB = b;
answerA = a+c;
}
int temp = gcd(answerA, answerB);
cout << answerA/temp << " " << answerB/temp << "\n";
}
18.백준(2512) 예산
이분탐색 알고리즘 중 하나를 이용하면 쉽게 해결이 가능하다
- 주어진 조건에 맞게 변수에 분수 값 대입
- 유클리드 호제법을 이용하여 값을 구함
- 분모와 분자를 2번에서 얻은 값으로 나눠 줌
#include <cstdio>
#define MAX 100001
int money[MAX];
int main(void) {
int N, M;
scanf("%d", &N);
int maximum = 0;
for(int i = 0; i < N; i++) {
scanf("%d", &money[i]);
if(maximum < money[i]) maximum = money[i];
}
scanf("%d", &M);
int left = 0;
int right = maximum;
int result = 0;
while(left <= right) {
int mid = (left + right) / 2;
int sum = 0;
for(int i = 0; i < N; i++) {
sum += (money[i] > mid ? mid : money[i]);
}
if(sum <= M) {
left = mid + 1;
result = (result > mid ? result : mid);
}
else
right = mid - 1;
}
printf("%d\n", result);
return 0;
}
19.백준(14425) 문자열 집합
2중 for문을 사용하면 시간초과에 걸리게 된다 Map을 활용하여 해결해야 한다.
- 주어진 조건에 맞게 string map 생성
- 다음 for문에서 입력을 받으면서 그 값이 map에 있는지 확인
- 입력이 끝난 후 정답값 출력
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N,M = 0;
cin >> N >> M;
map<string,int>Map;
for(int i=0; i<N; i++){
string str;
cin >> str;
Map.insert(make_pair(str, 1));
}
string test;
int answer = 0;
for(int i=0; i<M; i++){
string str;
cin >> str;
if(Map[str]!=0){
answer ++;
}
}
cout << answer << "\n";
return 0;
}
20.백준(15649) N과 M(1)
백트랙킹을 사용하여 해결하는 문제이다.
- 주어진 조건에 맞게 N과 M 입력
- 수열을 저장할 배열 생성
- 중복된 값을 사용했는지를 확인 할 배열 생성
- 재귀적으로 구현
- M과 K가 같으면 원하는 길이만큼의 수열이 저장되었으므로 출력 후 종료
- 1~N까지 반복
- 만약 해당 값이 사용되지 않았다면
- 중복을 방지하기 위해서 방문 체크
- 재귀적으로 k+1호출 -> 다음 상태 공간 트리로 이동
- 백트랙킹을 해야하므로 다시 방문 체크 해제
#include <iostream>
#define MAX_SIZE 9
using namespace std;
int arr[MAX_SIZE];
bool isUsed[MAX_SIZE];
void NandM(int k, int n, int m);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r" ,stdin);
int N = 0;
int M = 0;
cin >> N >> M ;
NandM(0, N, M);
return 0;
}
void NandM(int k, int n, int m){
if(k==m){ // 정해진 수열과 같아질 경우 배열에 들어있던 값들 출력
for(int i=0; i<m; i++)
cout << arr[i] << " ";
cout << "\n";
return;
}
for(int i=1; i<=n; i++) //1부터 주어진 n까지 백트랙킹 시작
{
if(isUsed[i]==false){ // 만약 해당 값이 사용되지 않았다면 상태 공간 트리에 추가
arr[k] = i; // 해당 값을 배열에 저장
isUsed[i] = true; // 중복을 방지하기 위해서 방문 체크
NandM(k+1, n, m); // 재귀적으로 호출
isUsed[i] = false; // 백트랙킹을 해야하므로 다시 방문 체크 해제
}
}
}
21.백준(15650) N과 M(2)
백트랙킹을 사용하여 해결하는 문제이며 이전 문제와 다르게 고른 수열은 오름차순이다.
- 주어진 조건에 맞게 N과 M 입력
- 수열을 저장할 배열 생성
- 중복된 값을 사용했는지를 확인 할 배열 생성
- 재귀적으로 구현
- M과 K가 같으면 원하는 길이만큼의 수열이 저장되었으므로 출력 후 종료
- 1~N까지 반복
- 만약 해당 값이 사용되지 않았고 이전에 선택된 트리의 값보다 크다면
- 중복을 방지하기 위해서 방문 체크
- 재귀적으로 k+1호출 -> 다음 상태 공간 트리로 이동
- 백트랙킹을 해야하므로 다시 방문 체크 해제
#include <iostream>
#define MAX_SIZE 9
using namespace std;
int arr[MAX_SIZE];
bool isUsed[MAX_SIZE];
void NandM(int k, int n, int m);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r" ,stdin);
int N = 0;
int M = 0;
cin >> N >> M;
NandM(0, N, M);
return 0;
}
void NandM(int k, int n, int m){
if(k==m){
for(int i=0; i<m; i++)
cout << arr[i] << " ";
cout << "\n";
return;
}
for(int i=1; i<=n; i++){
if(arr[k-1]<i && isUsed[i]==false) //이전에 선택된 값 보다 다음에 선택된 값이 더 크고 방문된 적 없다면
{
arr[k] = i;
isUsed[i] = true;
NandM(k+1, n, m);
isUsed[i] = false;
}
}
}
22.백준(15651) N과 M(3) #### 백트랙킹을 사용하여 해결하는 문제이며 이전 문제와 다르게 중복값을 허용하므로 방문 체크를 할 필요가 없다. 1. 주어진 조건에 맞게 N과 M 입력 2. 수열을 저장할 배열 생성 4. 재귀적으로 구현 - M과 K가 같으면 원하는 길이만큼의 수열이 저장되었으므로 출력 후 종료 - 1~N까지 반복 - 만약 해당 값이 사용되지 않았고 이전에 선택된 트리의 값보다 크다면 - 재귀적으로 k+1호출 -> 다음 상태 공간 트리로 이동 ![IMG_0874](https://user-images.githubusercontent.com/79856225/206670551-68e3920b-3ea2-48a5-b98d-56fa72a0b02d.jpg)
#include <iostream>
#define MAX_SIZE 8
using namespace std;
int arr[MAX_SIZE];
void NandM2(int k, int n, int m);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
int M = 0;
cin >> N >> M;
NandM2(0, N, M);
return 0;
}
void NandM2(int k, int n, int m)
{
if(k==m){
for(int i=0; i<m; i++){
cout << arr[i] << " ";
}
cout << "\n";
return ;
}
for(int i=1; i<=n; i++) //중복값도 허용하므로 방문체크를 할 필요가 없음
{
arr[k] = i;
NandM2(k+1, n, m);
}
}
23.백준(15652) N과 M(4)
백트랙킹을 사용하여 해결하는 문제이며 이전 2와 3을 합친 버전
- 주어진 조건에 맞게 N과 M 입력
- 수열을 저장할 배열 생성
- 재귀적으로 구현
- M과 K가 같으면 원하는 길이만큼의 수열이 저장되었으므로 출력 후 종료
- 1~N까지 반복
- 만약 해당 값이 이전에 선택된 트리의 값보다 크다면
- 재귀적으로 k+1호출 -> 다음 상태 공간 트리로 이동
#include <iostream>
#define MAX_SIZE 9
using namespace std;
int arr[MAX_SIZE];
void NandM_4(int k, int n, int m);
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
int M = 0;
cin >> N >> M;
NandM_4(0, N, M);
return 0;
}
void NandM_4(int k, int n, int m)
{
if(k==m){
for(int i=0; i<m; i++){
cout << arr[i] << " ";
}
cout << "\n";
return ;
}
for(int i=1; i<=n; i++){ // 오름차순으로 정렬해야 하므로 이전에 들어간 값보다 다음값이 크다면 진행
if(arr[k-1]<=i)
{
arr[k] = i;
NandM_4(k+1, n, m);
}
}
}
24.백준(15654) N과 M(5)
백트랙킹을 사용하여 해결하는 문제이며 이전 2와 3을 합친 버전
백트랙킹을 사용하여 해결하는 문제이며 특정 N값의 수열만 추출
- 주어진 조건에 맞게 N과 M 입력
- 수열을 저장할 배열 생성
- 특정 숫자만 담을 배열 생성
- 재귀적으로 구현
- M과 K가 같으면 원하는 길이만큼의 수열이 저장되었으므로 출력 후 종료
- 1~N까지 반복
- 만약 해당 값이 이전에 선택 된 적 없다면
- 재귀적으로 k+1호출 -> 다음 상태 공간 트리로 이동
#include <iostream>
#include <vector>
#include <algorithm>
#define MAX 9
#define MAX_SIZE 10001
using namespace std;
int arr[MAX];
bool isUsed[MAX_SIZE];
void NandM5(vector<int>&v, int k, int n, int m);
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
int M = 0;
cin >> N >> M;
vector<int>v(N, 0);
for(int i=0; i<N; i++)
cin >> v[i];
sort(v.begin(), v.end());
NandM5(v, 0, N, M);
return 0;
}
void NandM5(vector<int>&v, int k, int n, int m)
{
if(k==m){
for(int i=0; i<m; i++)
cout << arr[i] << " ";
cout << "\n";
return ;
}
for(int i=0; i<n; i++){
if(isUsed[v[i]] == false){
arr[k] = v[i];
isUsed[v[i]] = true;
NandM5(v, k+1, n, m);
isUsed[v[i]] = false;
}
}
}
25.백준(17175) 피보나치는 지겨웡~
동적프로그래밍 메모제이션을 활용하여 해결할 수 있는 문제이다.
- 피보나치 횟수만큼 호출한다면 시간초과가 나는 문제이므로 동적프로그래밍을 활용한다.
- 피보나치 식과 똑같이 점화식을 이용하여 해결
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int dp[51];
int fibonacci(int n);
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r" ,stdin);
int n = 0;
cin >> n;
dp[0] = 1;
dp[1] = 1;
int fibo = fibonacci(n);
cout << fibo << "\n";
return 0;
}
int fibonacci(int n) { // 호출
if(dp[n]!=0){
return dp[n];
}
else{
dp[n] = (fibonacci(n-2) + fibonacci(n-1) +1) % 1000000007;
return dp[n];
}
}
26.백준(13417) 카드 문자열
단순 구현 문제이므로 덱 또는 벡터를 써서 해결이 가능
- 기준 점 벡터를 생성
- 기준점을 비교하여 사전순으로 더 빠르면 큐 느리면 스택
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt","r", stdin);
int testCase = 0;
cin >> testCase;
while(testCase--)
{
vector<char>V;
int numOfCard = 0 ;
cin >> numOfCard;
char ch;
cin >> ch;
V.push_back(ch);
// 기준점 삽입
for(int i=1; i<numOfCard; i++){
cin >> ch;
if(V[0]<ch)// 뒤에 붙는 경우
{
V.push_back(ch);
}
else //앞에 붙는 경우
{
V.insert(V.begin(), ch);
}
}
for(int i=0; i<numOfCard; i++){
cout << V[i];
}
cout <<"\n";
}
return 0;
}
———————-
백준_실버_4
1.백준(1979) 소수 찾기
풀이: 제일처음 미리 에라스토네스의 체를 이용하여 ans벡터안의 소수들을 체크한 이후에 주어진 값들의 인덱스가 0이라면 소수 -> 카운트 1 증가
# 에라토스테네스의 체는 소수의 개수를 구할 때 상당히 빠른 속도를 보여준다!
#include <iostream>
#include <vector>
#define N 1000000
using namespace std;
int main(){
int cnt = 0;
int Num;
cin >> Num;
vector<int>ans(N+1,0);
ans[0]=1; // 0 제외
ans[1]=1; // 1 제외
for(int i=2; i*i<=N; i++){
if(ans[i]==1){
continue;
} //이미 소수의 배수이면 넘어감
else{
for(int j=2*i; j<=N; j=j+i)
ans[j] = 1; //소수의 배수를 제거
}
}
while(Num--)
{
int prime=0;
cin >> prime;
if(ans[prime] == 0){cnt++;}
}
cout << cnt;
return 0;
}
2.백준(10828) 스택
풀이 단순하게 스택을 구현하는 문제 자료구조에서 스택을 많이 구현해봤기때문에 정말 쉽게 풀 수 있었다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100000
typedef struct Stack{
int data[SIZE];
int top;
}Stack; //Stack 정의
void init(Stack *S){
S->top = -1;
} // 시작 시 스택의 화살표를 -1로
int full(Stack *S){
return S->top==(SIZE-1);
} //스택이 꽉 찼는지 확인
int empty(Stack *S){
return S->top==-1;
} //스택이 비었는지 확인
void push(Stack *S, int elem)
{
if(full(S)){
}
else{
S->top ++;
S->data[S->top] = elem;
}
} //꽉 차있는지를 확인 후 원하는 값 삽입
int pop(Stack *S){
if(empty(S)){
return -1;
}
else{
int temp = S->data[S->top];
S->top--;
return temp;
}
} //비어있는지 확인 후 스택의 맨 마지막을 제거 후 리턴
int size(Stack *S){
return S->top+1;
} //스택의 사이즈를 리턴
int top(Stack *S){
if(empty(S)){
return -1;
}
else{
return S->data[S->top];
}
} //스택의 맨 마지막 값만을 리턴 제거X
int main(){
int N ;
int elem = 0;
int len =0;
char str[100];
char *check = "push";
char *check1 = "pop";
char *check2 = "size";
char *check3 = "empty";
char *check4 = "top";
scanf("%d", &N);
Stack S;
init(&S);
for(int i=0; i<N; i++){
scanf("%s",str);
if(!strcmp(str, check)) // 같으면 0
{
scanf("%d", &elem);
push(&S,elem);
}
else if(!strcmp(str, check1))
{
printf("%d\n",pop(&S));
}
else if(!strcmp(str, check2)){
printf("%d\n",size(&S));
}
else if(!strcmp(str, check3)){
printf("%d\n",empty(&S));
}
else if(!strcmp(str, check4)){
printf("%d\n",top(&S));
}
}
return 0;
}
3. 백준(10845) 큐
풀이 : 원형큐가 아닌 선형큐를 구현하는 문제이므로 손쉽게 구현이 가능하다 단순히 큐에대한 개념을 물어보는 문제
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100000
typedef struct {
int data[SIZE];
int front;
int rear;
}QueueType;
void init(QueueType *Q)
{
Q->front = 0;
Q->rear = -1;
}
int empty(QueueType *Q)
{
return Q->rear < Q->front;
}
void push(QueueType *Q, int elem){
Q->data[++Q->rear] = elem;
}
int pop (QueueType *Q){
if(empty(Q)){
return -1;
}
else{
return Q->data[Q->front++];
}
}
void size(QueueType *Q){
printf("%d\n", (Q->rear+1)- (Q->front));
}
int front(QueueType *Q){
if(empty(Q)){return -1;}
return Q->data[Q->front];
}
int back(QueueType *Q){
if(empty(Q)){return -1;}
return Q->data[Q->rear];
}
int main(void){
char *Push = "push";
char *Pop = "pop";
char *Size = "size";
char *Empty = "empty";
char *Front = "front";
char *Back = "back";
QueueType Q;
init(&Q);
int N = 0;
scanf("%d", &N);
for(int i=0; i<N; i++){
char str[100];
scanf("%s", str);
if(strcmp(Push, str)==0){
int num = 0;
scanf("%d", &num);
push(&Q,num);
}
else if(!strcmp(Pop, str))
printf("%d\n", pop(&Q));
else if(!strcmp(Size, str))
size(&Q);
else if(!strcmp(Empty, str))
printf("%d\n", empty(&Q));
else if(!strcmp(Front, str))
printf("%d\n", front(&Q));
else
printf("%d\n", back(&Q));
}
return 0;
}
4.백준(1026) 보물
풀이 : 오름차순 정렬과 내림차순 정렬을 이용하면 곱할때 항상 최솟값을 만들 수 있다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >>N;
vector<int>A(N,0);
vector<int>B(N,0);
int sum =0;
for(int i=0; i<N; i++){
int temp = 0;
cin >> temp;
A[i] = temp;
}
for(int i=0; i<N; i++){
int temp = 0;
cin >> temp;
B[i] = temp;
}
sort(A.begin(), A.end());
sort(B.rbegin(), B.rend());
for(int i=0; i<N; i++){
sum += A[i] * B[i];
}
cout << sum <<"\n";
return 0;
}
5. 백준(10773) 제로
풀이: 스택을 이용하여 만약에 0이 아닌 수가 들어오면 스택에 저장하고 0이 들어온경우는 pop으로 스택값을 제거해준 후 나머지 스택의 모든원소를 더해주면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N ;
cin >> N;
stack<int> S;
while(N--){
int Num ;
cin >> Num;
if(Num ==0)
S.pop();
else
S.push(Num);
}
long long Sum = 0;
while(!S.empty())
{
long long temp = 0;
temp = S.top();
S.pop();
Sum = Sum + temp;
}
cout << Sum <<"\n";
return 0;
}
6.백준(10866) 덱
풀이
STL라이브러리 덱을 사용하여도 충분히 통과하는 문제이지만 포인터를 이용하여 덱을 직접구현해서 해결
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct Node{
int data;
struct Node *next;
}Node;
void init(Node *deque)
{
deque->next = NULL;
}
int empty(Node *deque){
return deque->next == NULL;
}
void push_front(Node *deque, int n)
{
Node *node = (Node*)malloc(sizeof(Node));
node->data = n;
node->next = deque->next;
deque->next = node;
}
void push_back(Node *deque, int n)
{
Node *node = (Node*)malloc(sizeof(Node));
Node *p = deque;
while(p->next!=NULL)
{
p= p->next;
}
node->data = n;
p->next = node;
node->next = NULL;
}
int pop_front(Node *deque)
{
if(empty(deque)){
return -1;
}
Node *p = deque->next;
int temp = p->data;
deque->next = p->next;
free(p);
return temp;
}
int pop_back(Node *deque)
{
if(empty(deque)){
return -1;
}
Node *q = deque; //헤드
Node *p = deque->next;
while(p->next!=NULL){
p = p->next;
q = q->next;
}
int temp = p->data;
q->next = NULL;
free(p);
return temp;
}
int size(Node *deque){
Node *p = deque->next;
int cnt =0;
while(p!=NULL){
p= p->next;
cnt++;
}
return cnt;
}
int front(Node * deque){
if(empty(deque))
return -1;
return deque->next->data;
}
int back(Node * deque){
if(empty(deque))
return -1;
Node *p = deque->next;
while(p->next!=NULL){
p = p->next;
}
return p->data;
}
void print(Node *deque)
{
Node *p = deque->next;
while(p!=NULL){
cout << p->data <<"\n";
p = p->next;
}
}
int main(){
Node *deque = (Node*)malloc(sizeof(Node));
init(deque);
int N = 0;
cin >> N;
while(N--){
string str;
cin >> str;
if(str =="push_front"){
int num =0;
cin >> num;
push_front(deque, num);
}
else if(str=="push_back"){
int num = 0;
cin >> num;
push_back(deque, num);
}
else if (str=="pop_front"){
cout << pop_front(deque) <<"\n";
}
else if (str=="pop_back"){
cout << pop_back(deque) << "\n";
}
else if(str=="size"){
cout << size(deque) <<"\n";
}
else if(str=="empty"){
cout << empty(deque)<<"\n";
}
else if(str=="front"){
cout << front(deque) <<"\n";
}
else if(str=="back"){
cout << back(deque) << "\n";
}
}
return 0;
}
7. 백준(9012) 괄호
- 스택을 이용하여 ‘(‘가 나오면 push ‘)’가 나오면 pop을 해줘서 괄호의 쌍이 맞는지 확인해주는 스택응용의 기본문제이다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int Num = 0;
bool check = false;
cin >> Num;
string ans;
while(Num--)
{
stack<char>S; // 스택생성
string str;
cin >> str;
check = false;
for(int i=0; i<str.length(); i++)
{
if(str[i] == '(') //열린괄호이면 스택에 푸쉬 하고 정상종료 true
{
S.push(str[i]);
check = true;
}
else //닫힌괄호인데 이미 스택이 비어있으면 오류종료 false 후 break 그게 아니라면 스택에서 pop
{
if(S.empty()){check = false; break;}
S.pop();
}
}
if(S.empty() && check == true)
ans = "YES";
//스택이 정상종료 되었으면서 비어있다면 쌍이 맞음
else // 스택이 비정상종료 또는 비어있지않다면 쌍이 맞지 않음
ans = "NO";
cout << ans <<"\n";
}
return 0;
}
8. 백준(2164) 카드2
- 큐를 이용하는 문제로 큐에대한 개념만 알고있다면 어렵지않게 해결이 가능한 문제이다.
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
queue<int>card;
for(int i=0; i<N; i++)
card.push(i+1);
while(card.size()!=1)
{
card.pop(); // 맨 처음 제거
card.push(card.front()); //맨 처음 뒤로
card.pop(); // 맨 처음 제거
}// while
cout << card.front() << "\n";
return 0;
}
9.백준(4949) 균형잡힌세상
- 스택을 이용하여 풀면 되는 문제이다. 두 가지 종류의 괄호가 나오기 때문에 닫힌괄호와 이전 열린괄호가 같지않는경우도 체크해줘야 한다 스택을 이용하여 풀면 높은 난이도 문제는 아니다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <string>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
while(true)
{
string str;
stack<char>world;
bool check = false;
getline(cin , str);
if(str[0]=='.'){break;}// 첫 입력이 '.'라면 반복 종료
for(int i=0; str[i]!='.'; i++){ // 마침표가 나오기 전까지 확인
switch(str[i]){
case '(':
world.push(str[i]); //열린 괄호가 나온다면 스택에 푸쉬
break;
case '[':
world.push(str[i]); //열린 괄호가 나온다면 스택에 푸쉬
break;
case ')': //닫힌 괄호가 나왔을때 스택이 비어있지않고(같은 괄호가 한 쌍) , 이전에 들어온 괄호랑 짝이 맞으면 팝
if(world.empty()){check = true; break;} // 쌍이 아닌경우
if(world.top() != '('){check = true; break;} // 같은 종료의 괄호가 아닌 경우
world.pop();
break;
case ']': //닫힌 괄호가 나왔을때 스택이 비어있지않고(짝이 맞고) , 이전에 들어온 괄호랑 짝이 맞으면 팝
if(world.empty()){check = true; break;}
if(world.top() != '['){check = true; break;}
world.pop();
break;
} //switch
} // 마침표전까지 문자열을 검사하는 for문
if(world.empty() && check == false){
cout << "yes\n" ;
} //정상적으로 끝난경우
else{
cout << "no\n";
}
}
return 0;
}
10. 백준(11866) 요세푸스 문제 0
- 원형큐를 이용하여 풀면 되는문제이다 원형큐의 순환과정만 안다면 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N,K;
cin >> N >> K ;
int idx = K-1;
vector<int> ans;
for(int i=0; i<N; i++)
ans.push_back(i+1);
cout << "<";
for(int i=0; i<N-1; i++){
cout << ans[idx] << ", ";
ans.erase(ans.begin() +idx);
idx = (idx+ K-1)% ans.size() ;
}
cout << ans.back();
cout << ">\n";
return 0;
}
11. 백준(10816) 숫자 카드 2
- STL함수 binary serach를 이용하여 푸는 문제이다. 시간이 된다면 직접구현해보면 좋을듯
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int Num = 0;
cin >> Num;
vector<int>card(Num, 0);
for(int i=0;i <Num; i++){
cin >> card[i];
}
stable_sort(card.begin(), card.end());
int check = 0;
cin >> check;
for(int i=0; i<check; i++){
int search = 0 ;
cin >> search;
cout << upper_bound(card.begin(), card.end() , search) - lower_bound(card.begin(), card.end(), search) << " ";
//upper_bound를 이용하면 값을 주어진 값을 기준으로 가장 큰 값의 idx를 알 수 있음
//lower_bound를 이용하면 값을 기준으로 가장 작은 값의 idx를 알 수 있음
}
return 0;
}
12. 백준(1620) 나는야 포켓몬 마스터 이다솜
- STL함수 map을 이용하여 푸는 문제이다 키와 밸류 개념을 확실하게 잡아야 할 필요가 있다고 느껴진다.
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt" , "r", stdin);
int Num , Target;
cin >> Num >> Target;
map<string, int>DOGAM;
vector<string>DOGAM2;
for(int i=1; i<=Num; i++){
string name;
cin >> name;
DOGAM.insert(make_pair(name,i));
DOGAM2.push_back(name);
}
while(Target--){
char str[100];
cin >> str;
// cout << atoi(str) << "\n"
// 정수를 입력받으면 그대로 나오고 문자열을 입력받으면 0이 나오넹
if(atoi(str))
cout << DOGAM2[atoi(str)-1] << "\n";
else
cout << DOGAM[string(str)] << "\n";
}
return 0;
}
13. 백준(1764) 듣보잡
- STL함수 map을 이용하여 푸는 문제이다 위 문제와 함께 개념잡기 좋은 문제이다.
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
bool com(string a, string b){
return a>b;
} //사전순 정렬
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin);
int notListend = 0;
int notSaw = 0;
cin >> notListend >> notSaw;
map<string ,int>Answer;
vector<string>list;
for(int i=0; i<notListend; i++){
string str;
cin >> str;
Answer.insert(make_pair(str, i+1));
}
// 들어보지 못한 인물들을 map에 insert
for(int i=0; i<notSaw; i++){
string str;
cin >> str;
// 보지못한 인물들이 map에 있는지 확인 이때 만약 존재하지않는다면 0을 리턴해준다.
if(Answer[str]!=0)
list.push_back(str);
}
stable_sort(list.begin(), list.end());
cout << list.size() <<"\n";
for(vector<string>::iterator it = list.begin(); it!= list.end(); it++)
cout << *it << "\n";
return 0;
}
14. 백준(1158) 요세푸스
- 벡터에 대한 개념을 물어보는 문제 있거 같기도 하다 방문 배열을 만들어서 해결하였다.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
queue<int>Q;
vector<int>V;
int N,K = 0;
cin >> N >> K;
vector<int>visit(N+1, 0);
K--;
int idx = K;
for(int i=1; i<=N; i++)
V.push_back(i);
if(N==1){Q.push(1); } //예외 처리
else{
Q.push(V[idx]);
visit[idx+1] = 1;
V.erase(V.begin()+idx);
while(V.size()!=0){
idx = (idx+K)%V.size();
if(visit[V[idx]]==0){
visit[V[idx]]=1;
Q.push(V[idx]);
V.erase(V.begin()+idx);
}
}
}
cout << "<";
while(!Q.empty()){
if(Q.size()==1){
cout << Q.front();
Q.pop();
}
else{
cout << Q.front() << ", ";
Q.pop();
}
}
cout << ">\n";
return 0;
}
15. 백준(17219) 비밀번호 찾기
- key value에 대한 개념을 물어보는 문제이며 map 라이브러리를 사용하면 쉽게 해결이 가능하다.
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N,M;
cin >> N >> M;
map<string ,string>Passward;
for(int i=0; i<N; i++){
string site;
string pw;
cin >> site >> pw;
Passward.insert(make_pair(site, pw));
}
for(int i=0; i<M; i++){
string site;
cin >> site;
cout << Passward[site] <<"\n";
}
return 0;
}
16. 백준(2960) 에라토스테네스의 체
- 소수를 구하는 방법 중 하나인 에라토스테네스의 체에 대해 알고있으면 쉽게 해결이 가능한 문제이다.
#include <iostream>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
int K = 0;
cin >> N >> K;
vector<int>V(N+1, 0);
int answer = 0;
int count = 0;
for(int i=2; i<=N; i++){
if(V[i]==0){
for(int j=i; j<=N; j= j+i){
if(V[j] ==0){
V[j] =1;
count ++;
if(count == K){
answer = j;
break;
}
}
}
}
}
cout << answer << " ";
return 0;
}
17. 백준(18258) 큐 2
- 큐에 대한 개념을 물어보는 문제이며 STL queue를 이용하면 쉽게 해결이 가능한 문제이다.
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
queue<int>Q;
int testCase = 0;
cin >> testCase;
string str;
while(testCase--){
cin >> str;
if(str=="push"){
int temp = 0;
cin >> temp;
Q.push(temp);
}
else if(str=="pop"){
if(!Q.empty()){
int temp = Q.front();
Q.pop();
cout << temp << "\n";
}
else{
cout << -1 <<"\n";
}
}
else if(str=="size"){
cout << Q.size() <<"\n";
}
else if(str=="empty"){
cout << Q.empty() << "\n";
}
else if(str=="front"){
if(!Q.empty()){
int temp = Q.front();
cout << temp << "\n";
}
else{
cout << -1 <<"\n";
}
}
else if(str=="back"){
if(!Q.empty()){
int temp = Q.back();
cout << temp << "\n";
}
else{
cout << -1 <<"\n";
}
}
}
return 0;
}
17. 백준(10825) 국영수
- 정렬 기준을 정할 수 있는지에 대해 물어보는 문제이다 정렬 기준에 대한 개념만 있다면 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
typedef struct Studnet{
string name;
int KoreanScore;
int EnglishScore;
int MathScore;
}student;
bool com(student A, student B){
if(A.KoreanScore>B.KoreanScore) //국어 성적 내림차순
return true;
if(A.KoreanScore == B.KoreanScore){ //국어 성적이 같다면
if(A.EnglishScore<B.EnglishScore){return true;} //영어 점수 오름차순
if(A.EnglishScore == B.EnglishScore){ //국어, 영어 점수가 같다면
if(A.MathScore>B.MathScore){return true;} //수학 점수 내림차순
if(A.MathScore==B.MathScore){ //국영수 점수 모두 같다면 사전순으로 정렬
if(A.name <B.name){return true;}
}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N ;
string name;
int KoreanScore;
int EnglishScore;
int MathScore;
vector<student>V(N);
for(int i=0; i<N; i++){
cin >> name >> KoreanScore >> EnglishScore >> MathScore;
V[i].name = name, V[i].KoreanScore = KoreanScore, V[i].EnglishScore=EnglishScore , V[i].MathScore=MathScore;
}
sort(V.begin(), V.end(), com);
for(int i=0; i<N; i++){
cout << V[i].name <<"\n";
}
return 0;
}
18. 백준(1302) 베스트셀러
- Map에 대한 개념을 물어보는 문제이며 Map 라이브러리를 활용하여 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
int main(void){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int number = 0;
cin >> number;
map<string, int>m;
string str;
for(int i=0; i<number; i++){
cin >> str;
if(m.count(str)==0){
m.insert(make_pair(str, 1));
}
else{
m.insert(make_pair(str, m[str]++));
}
}
int max = 0;
string answer;
for(auto M : m){
if(max < M.second){
max = M.second;
answer = M.first;
}
}
cout << answer << "\n";
return 0;
}
19. 백준(2776) 암기왕
- Map을 이용해서 풀 수 있는 문제이다. 카운팅 정렬을 이용하여 해결하려 했지만 계속 오류가 난다. 해결 후 방법 메모해야 함
#include <iostream>
#include <vector>
#include <algorithm>
#define MAX_SIZE 1000001
using namespace std;
void Init(vector<int> &arr );
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int testCase = 0;
cin >> testCase;
vector<int>Note(MAX_SIZE,0);
while(testCase--){
int n = 0;
cin >> n;
for(int i=0; i<n; i++){
int idx = 0;
cin >> idx ;
Note[idx-1] ++;
}
int m = 0;
cin >> m;
for(int i=0; i<m; i++){
int idx = 0;
cin >> idx;
if(Note[idx-1]!=0){
Note[idx-1]--;
cout << 1 << "\n";
}
else{
cout << 0 << "\n";
}
}
Init(Note);
}
return 0;
}
void Init(vector<int> &arr ){
for(int i=0; i<MAX_SIZE; i++){
arr[i] = 0;
}
}
20. 백준(24060) 알고리즘 수업 - 병합 정렬 1
- 정렬 방법 중 하나인 병합 정렬에 대한 개념을 알면 쉽게 해결할 수 있는 문제이다
- 중간에 메모리 초과가 날 수 있으니 사용했던 배열은 delte[]를 이용하여 동적 메모리 공간을 해제해야 한다.
#include <iostream>
using namespace std;
void buildArr(int *arr, int size);
void checkArr(int *arr, int size);
void merge(int *arr ,int start, int mid, int end, int sz);
void mergeSort(int *arr, int start, int end, int sz);
int saveCnt;
int TARGET;
int ANSWER;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt","r",stdin);
int size = 0;
int target = 0 ;
cin >> size >> target;
TARGET = target;
int *arr = new int[size];
buildArr(arr,size);
mergeSort(arr,0,size-1,size);
if(saveCnt<TARGET){cout << -1 << "\n";}
else{cout << ANSWER <<"\n";}
return 0;
}
void buildArr(int *arr, int size){
for(int i=0; i<size; i++){
cin >> arr[i];
}
}
void checkArr(int *arr, int size){
for(int i=0; i<size; i++){
cout << arr[i] << " ";
}
cout << "\n";
}
void mergeSort(int *arr, int start, int end, int sz){
if(start<end){
int mid = (start+end)/2;
mergeSort(arr, start, mid,sz);
mergeSort(arr, mid+1, end,sz);
merge(arr, start, mid,end,sz);
}
}
void merge(int *arr ,int start, int mid, int end, int sz){
int *temp = new int[sz];
int i = start; //이미 정렬된 좌측
int j = mid+1; // 이미 정렬된 우측부터
int idx = start; // 정렬된 좌측부터 시작
while(i<=mid && j<=end ){
if(arr[i]<arr[j]){
saveCnt++;
if(TARGET == saveCnt)
ANSWER = arr[i];
temp[idx++] = arr[i++];
}
else {
saveCnt++;
if(TARGET == saveCnt)
ANSWER = arr[j];
temp[idx++] = arr[j++];
}
}
while(i<=mid){
saveCnt++;
if(TARGET == saveCnt)
ANSWER = arr[i];
temp[idx++] = arr[i++];
}
while(j<=end){
saveCnt++;
if(TARGET == saveCnt)
ANSWER = arr[j];
temp[idx++] = arr[j++];
}
for(int i=start; i<=end; i++){
arr[i] = temp[i];
}
delete[] temp;
}
21. 백준(2217) 로프
- 정렬을 사용하여 간단한 방법으로 해결이 가능하다.
- 가장 큰 로프부터 *i
- 그 중 최댓값
- 가장 큰 로프부터 *i
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int number = 0;
cin >> number;
vector<int>lope(number, 0);
for(int i=0; i<number; i++)
cin >> lope[i];
//
sort(lope.rbegin(), lope.rend());
int k = 0;
int weightMax = 0;
int value = 0;
for(int i=1; i<= number; i++){
value = lope[i-1] * i;
if(weightMax<value){
weightMax = value;
k = i;
}
}
cout << weightMax << "\n";
return 0;
}
22. 백준(12927) 배수 스위치
- 단순 구현 문제
#include <iostream>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
string light;
cin >> light;
int answer = 0;
int len = light.length();
for(int i=1; i<=len; i++)
{
if(light[i-1] == 'Y'){
answer ++;
for(int j= i; j<= len; j = j+i)
{
if(light[j-1] == 'Y')
light[j-1] = 'N';
else
light[j-1] = 'Y';
}
}
}
cout << answer << "\n";
return 0;
}
23. 백준(9372) 상근이의 여행
- 너비 우선 탐색 BFS 문제
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
int BFS(vector<int>G[], vector<int>&visit,queue<int> &Q, int cnt);
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
int testCase = 0;
cin >> testCase;
while(testCase--){
int country = 0;
int airplan = 0;
cin >> country >> airplan;
vector<int>G[country+1];
vector<int>visit(country+1, 0);
for(int i=0; i<airplan; i++){
int a, b ;
cin >> a >> b;
G[a].push_back(b);
G[b].push_back(a);
}
// 양방향 그래프 연결
queue<int>Q;
Q.push(1);
// 최초 1번 노드 삽입 후 여행시작
int answer = BFS(G,visit, Q,0);
cout << answer-1 << "\n";
}
return 0;
}
int BFS(vector<int>G[], vector<int>&visit,queue<int> &Q, int cnt)
{
if(!Q.empty()) // 큐의 원소가 하나라도 있다면
{
int temp = Q.front();
Q.pop();
cnt++;
visit[temp] = 1;
// 원소 제거 후 방문 처리
for(vector<int>::iterator it = G[temp].begin(); it!= G[temp].end(); it++){
if(visit[*it]==0){ // 최초 방문
visit[*it] = 1; //방문 체크
Q.push(*it); //큐 삽입
cnt = BFS(G,visit,Q,cnt); //BFS는 바로 진행
}
}
}
return cnt;
}
———————-
백준_실버_5
1. 그룹단어체커
풀이 : 알파벳배열을 만들고 특정 단어가 나오면 알파벳 배열의 1을 넣고 연속인지 체크
만약 배열의 1이 있으면서 체크랑도 다르다면 그건 중복된 숫자가 나왔으면서 연속도 아니라는 의미! 따라서 카운트 1 올리고 break
모든 반복 이후
총 반복횟수 - 그룹단어카운트 = 정답!
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main(){
cin.tie(NULL);
ios_base::sync_with_stdio(false);
int testCase;
int check = 0;
int cnt = 0;
cin >>testCase;
int temp =testCase;
while(testCase--){
int alpha[27] = {0};
string str ;
cin >> str;
int len = str.length();
check = 0;
for(int i=0; i<len; i++){
if(alpha[str[i]-97]==0){
alpha[str[i]-97] = 1;
check = str[i];
}
if(check == str[i])
continue;
else{
cnt++;
break;
}
}
}
int sum = temp - cnt ;
cout << sum <<endl;
return 0;
}
2. 백준 1425 소트인사이드
배열을 정렬하는 것은 쉽다. 수가 주어지면, 그 수의 각 자리수를 내림차순으로 정렬해보자.
입력
첫째 줄에 정렬하려고 하는 수 N이 주어진다. N은 1,000,000,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 자리수를 내림차순으로 정렬한 수를 출력한다.
풀이 : 이 문제는 벡터를 이용하면 간단하게 해결이 가능하다. 먼저 입력받은 정수의 각 자리수를 벡터의 담아 준 후 벡터를 내림차순으로 정렬해주면 정답 !
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
int N;
cin >> N;
vector<int>ans;
while(N!=0){
ans.push_back(N%10);
N = N/10;
}
sort(ans.rbegin(), ans.rend());
vector<int>:: iterator it = ans.begin();
for(; it!=ans.end(); it++){
cout << *it;
}
return 0;
}
3.백준(2751) 수정렬하기2
퀵정렬 알고리즘을 이용하여 풀면 쉽게 풀 수 있다. algorithm에 sort()함수는 퀵정렬이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N =0;
cin >> N;
vector<int>ans;
for(int i=0; i<N; i++){
int temp = 0;
cin >> temp;
ans.push_back(temp);
}
sort(ans.begin(), ans.end());
for(int i=0; i<N; i++)
cout << ans[i] << "\n";
return 0;
}
4.백준(4673) 셀프넘버
풀이 : 셀프넘버의 생성자를 이해하는데 한참이 걸렸다 쉽게 생각하면 1부터 셀프넘버를 계산해서 한번이라도 나온다면 생성자이다.
ex) d(1) -> 2 벡터의 2번 인덱스-> false
ex) d(2) -> 4 벡터의 4번 인덱스 -> false
….
ex) d(10) -> 11 벡터의 11번 인덱스 ->false
이렇게 크기가 10000짜리인 벡터를 생성해서 모두 셀프넘버라고 가정하고 한번이라도 나온 숫자는 False로바꿔준다. 그리고 벡터안의 true값인것은 한번도 나오지않은 숫자이므로 true값만 출력해주면 통과할 수 있다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int selfNum(int N)
{
int Sum = 0;
Sum = N;
while(N!=0){
Sum += N%10;
N = N/10;
}
return Sum;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
vector<bool>Self(10000+1, true);
for(int i=1; i<=10000; i++){
int NotSelf = selfNum(i); //2
if(NotSelf>10000)
continue;
Self[NotSelf] = false;
}
for(int i=1; i<=10000; i++)
if(Self[i]==true)
cout <<i <<"\n";
return 0;
}
5.백준(10814) 나이순 정렬
- Stable_sort 라는 새로운 정렬함수를 알게 되었음 (기준이 같다면 기존 순서를 유지해줌)
풀이 :
정수와 문자열을 가진 구조체를 선언 한 후 algorithm 라이브러리의 sort함수의 정렬기준을 새롭게 정의 해주면 쉽게 풀 수 있다. 만약 기준이 같다면 기존 순서를 유지해줘야 함 -> stable_sort함수를 이용
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
typedef struct sortAge{
int age;
string name;
}Age; // 나이와 이름을 가진 구조체 선언
bool compare(const Age & A, const Age &B){
if(A.age < B.age){
return true; //나이를 기준으로 오름차순 정렬
}
else{
return false;
}
} //sort 함수의 구조체를 넘겨줘야 함 또한 나이순으로 정렬
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int testCase;
cin >> testCase;
int N = testCase;
vector<Age>ans(testCase);
int idx = 0;
while(testCase--){
int a;
string n;
cin >> a >> n;
ans[idx].age = a;
ans[idx++].name = n;
}//while
stable_sort(ans.begin(), ans.end(), compare); //위에 정의한 기준으로 정렬 + stable_sort를 사용함으로 값이 같다면 기존의 순서 유지
for(int i=0; i<N; i++)
cout << ans[i].age << " " << ans[i].name << "\n";
return 0;
}
6. 백준(11651) 좌표정렬하기 2
- 기존 좌표정렬하기 변환문제이다. 새롭게 정의한 정렬기준으로 정렬해주면 쉽게 해결 가능
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
typedef struct {
int x;
int y;
}point;
bool compare(const point &a, const point &b){
if(a.y < b.y){
return true; // y를 기준으로 오름차순 정렬
}
else if(a.y == b.y){
return a.x < b.x; //y가 같다면 x를 기준으로 오름차순 정렬
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int testCase;
cin >> testCase;
int N = testCase;
vector<point>ans(testCase);
int idx = 0;
while(testCase--){
int x, y;
cin >> x >> y;
ans[idx].x = x;
ans[idx++].y = y;
} //testCase
stable_sort(ans.begin(), ans.end(), compare);
for(int i=0; i<N; i++){
cout << ans[i].x << " " << ans[i].y << "\n";
}
return 0;
}
7. 백준(1181) 단어정렬
- 기본정렬문제 새롭게 정의한 compare을 이용하여 정렬하여 해결가능
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
bool compare(string const &a, string const &b){
if(a.length()<b.length()){
return true;
}
else if(a.length() == b.length()){
return a<b;
}
else
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int Len;
cin >> Len;
vector<string>ans(Len);
for(int i=0 ;i<Len; i++){
string str;
cin >> str;
ans.push_back(str);
}
stable_sort(ans.begin(), ans.end(), compare);
ans.erase(unique(ans.begin(),ans.end()),ans.end());
for(vector<string>::iterator it = ans.begin()+1; it!=ans.end(); it++)
cout << *it << "\n";
return 0;
}
8. 백준(2581) 소수
- 에라토스테네스의 체를 이용하여 풀면 쉽게 해결 가능
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
vector<int>Prime(10000,0);
Prime[0] = 1;
Prime[1] = 1;
int M,N;
cin >> M >> N;
vector<int>ans;
int sum = 0;
for(int i=2; i*i<=N; i++){
for(int j=2*i; j<=N; j=j+i){
if(Prime[i]==0){
Prime[j] =1;
}
}
}
for(int i=M; i<=N; i++){
if(Prime[i] == 0){
sum += i;
ans.push_back(i);
}
}
sort(ans.begin(), ans.end());
if(ans.size()==0){
cout << "-1\n";
}
else{
cout << sum <<"\n";
cout << ans[0] ;
}
return 0;
}
9.백준(1018) 체스판 다시 칠하기
- CNN 신경망의 개념처럼 8x8윈도우를 이동시켜가면서 최솟값을 구하면 해결가능하다.
#include <iostream>
#include <vector>
using namespace std;
string White[8] ={
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW"
}; //흰색 체크보드
string Black[8] = {
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB"
}; //검은색 체크보드
int checkBoard(vector<vector<char> > chess, int i, int j){
int result_W = 0; // 흰 체크보드 결과
int result_B = 0; // 검은 체크보드 결과
for(int y=0; y<8; y++){ // 체스판을 전체를 돌아다님
string ans_w = White[y]; // 화이트보드 y번째 줄
string ans_b = Black[y]; // 블랙보드 y번째 줄
for(int x=0; x<8; x++){
if(ans_w[x]!=chess[y+i][x+j]) // 이동해야하므로 인덱스 + 매개변수 값
result_W++; // 화이트보드 필요한 수정개수
else if(ans_b[x]!=chess[y+i][x+j]) // 이동해야하므로 인덱스 + 매개변수 값
result_B++;// 블랙보드 필요한 수정개수
}
}
int min = result_W<=result_B?result_W:result_B; // 두 개의 보드의 최솟값 return
return min;
}//check fun
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N,M;
cin >> N >> M;
vector<vector<char> >chess(N, vector<char>(M));
for(int i=0; i<N; i++)
for(int j=0; j<M; j++)
cin >> chess[i][j] ;
int result = 10000000;
for(int i=0; i<N-7; i++){
for(int j=0; j<M-7; j++){
result = result<checkBoard(chess,i,j)?result:checkBoard(chess,i,j);
}
}
cout << result << "\n";
return 0;
}
10.백준(1436) 영화감독 숌
- string을 이용하여 단순반복으로 해결할 수 있는 문제이다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N = 0;
cin >> N;
int cnt = 0;
int Num = 665;
string str;
while (++Num)
{
str = to_string(Num);
if (str.find("666") != -1)
++cnt;
if (cnt == N)
{
cout << Num << "\n";
break;
}
}
return 0;
}
11. 백준(11732) 집합
- 집합을 구현하는 문제이다 STL라이브러리를 사용하면 시간초과가 계속 나서 배열로 구현하니 쉽게 해결 가능했다.
#include <iostream>
#include <string>
using namespace std;
int S[20];
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt" ,"r" ,stdin);
int numOfoperator = 0;
cin >> numOfoperator;
int value = 0;
while(numOfoperator--){
string str;
cin >> str;
if(str == "add"){
cin >> value;
if(S[value-1]==0){S[value-1] = 1;}
}
else if(str == "remove"){
cin >> value;
if(S[value-1] == 1){S[value-1] =0;}
}
else if(str == "check"){
cin >> value;
cout << (S[value-1]==1) <<"\n";
}
else if(str == "toggle"){
cin >> value;
if(S[value-1] == 1){S[value-1] = 0;}
else {S[value-1] = 1;}
}
else if(str == "all"){
for(int i=1; i<21; i++)
S[i-1] = 1;
}
else{
for(int i=1; i<21; i++)
S[i-1] = 0;
}
}
return 0;
}
12. 백준(11728) 배열 합치기
- 정렬 문제이다. 알고리즘 STL 라이브러리를 이용하면 쉽게 해결할 수 있다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt" ,"r", stdin);
int sizeA = 0;
int sizeB = 0;
cin >> sizeA >> sizeB;
vector<int>C(sizeA+sizeB, 0);
for(int i=0; i<sizeA+sizeB; i++)
cin >> C[i];
sort(C.begin(), C.end());
for(auto c : C)
cout << c << " ";
cout << "\n";
return 0;
}
13. 백준(10815) 숫자 카드
- 배열의 음수 인덱스 관리에 대해 이해가 있다면 어렵지 않게 해결할 수 있다.
#include <iostream>
#include <vector>
#include <algorithm>
#define SIZE 20000001
#define SZ 10000000
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
vector<int>Arr(SIZE,0);
// 주어진 정수의 크기만큼 배열을 미리 생성
for(int i=0; i<N; i++){
int temp = 0;
cin >> temp ;
if(temp<0){ //음수인 경우 따로 처리
temp = temp *-1;
Arr[SZ+temp] = 1;
}
else
Arr[temp] = 1;
}
int M = 0;
cin >> M;
vector<int>Answer(M,0);
int idx = 0;
for(int i=0; i<M; i++)
{
int temp = 0;
cin >> temp;
if(temp<0){
temp = temp *-1;
temp += SZ;
}
if(Arr[temp]==1)
Answer[idx++] = 1;
else
Answer[idx++] = 0;
}
// 해당 값이 있다면 정답 벡터에 1 삽입
for(auto a : Answer)
cout << a << " ";
cout << "\n";
return 0;
}
14.백준(11004) K번째 수
- 단순하게 정렬만 해주면 쉽게 해결이 가능하다.
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int main(void){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int size = 0;
int target =0 ;
cin >> size >> target;
vector<int>V(size, 0);
for(int i=0; i<size; i++)
cin >> V[i];
sort(V.begin(), V.end());
cout << V[target-1] << "\n";
return 0;
}
15.백준(11876) 중복 빼고 정렬하기
- 음수 인덱스를 처리하는 방법에 대해 알 수 있는 문제이다
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int number = 0;
cin >> number ;
vector<int>V(2002,0); //절댓값 처리
for(int i=0; i<number; i++){
int temp = 0;
cin >> temp;
if(temp <0){
if(V[temp+2001]==0)
V[temp+2001] = 1;
}
else{
if(V[temp] ==0)
V[temp] =1;
}
}
for(int i=1001; i<=2000; i++){
if(V[i] !=0){
cout << i-2001 << " ";
}
}
for(int i=0; i<=1000; i++){
if(V[i] !=0){
cout << i << " ";
}
}
return 0;
}
16.백준(5635) 생일
- 정렬 기준에 대한 개념을 물어보는 문제이며 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
typedef struct person{
string name;
int day;
int month;
int year;
}person;
bool com(person A, person B){
if(A.year > B.year){
return true;
}
if(A.year == B.year){
if(A.month >B.month){return true;}
if(A.month == B.month){
if(A.day > B.day){return true;}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt","r", stdin);
int num = 0;
cin >> num ;
vector<person>P(num);
person p;
for(int i=0; i<num; i++){
cin >> p.name >> p.day >> p.month >> p.year;
P[i].name = p.name;
P[i].day = p.day;
P[i].month = p.month;
P[i].year = p.year;
}
sort(P.begin(), P.end(), com);
cout << P[0].name << "\n" << P[num-1].name <<"\n";
return 0;
}
17.백준(11931) 수 정렬하기 4
- 정렬 기준에 대한 개념을 물어보는 문제이며 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r",stdin);
int num = 0;
cin >> num;
vector<int>V(num,0);
for(int i=0; i<num; i++){
cin >> V[i];
}
sort(V.rbegin(), V.rend());
for(int i=0; i<num; i++){
cout << V[i] <<"\n";
}
return 0;
}
18. 백준 2535 아시아 정보 올림피아드
- 정렬 기준에 대한 개념을 물어보는 문제이며 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct Asia{
int CountryNumber;
int StudentNumber;
int SuudentScore;
}Asia;
bool com(Asia A, Asia B){
return A.SuudentScore > B.SuudentScore;
// 점수를 기준으로 내림차순 정렬
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt","r", stdin);
int number = 0;
cin >> number;
vector<Asia>V(number);
for(int i=0; i<number; i++){
cin >> V[i].CountryNumber >> V[i].StudentNumber >> V[i].SuudentScore;
}
sort(V.begin(), V.end(), com);
vector<int>Cnt(10000,0);
// 국가별 인원수 체크를 하기 위한 배열
int idx = 0;
int anscnt = 0;
while(anscnt!=3){
Cnt[V[idx].CountryNumber]++; //국가별 인원 확인
if(Cnt[V[idx].CountryNumber] <=2 ){ //2명 이하면 출력
cout << V[idx].CountryNumber << " " << V[idx].StudentNumber << "\n";
idx++;
anscnt++;
}
else
idx++;
}
return 0;
}
19.백준(2822) 점수 계산
- 정렬 기준에 대한 개념을 물어보는 문제이며 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
#define SIZE 8
using namespace std;
typedef struct Quiz{
int number;
int Score;
}Q;
bool com(Q a, Q b){
return a.Score > b.Score;
}
bool com2(Q a, Q b){
return a.number < b.number;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin);
vector<Q>Quiz(SIZE);
for(int i=0; i<SIZE; i++){
cin >> Quiz[i].Score ;
Quiz[i].number = i+1;
}
sort(Quiz.begin(), Quiz.end(), com);
int sum = 0;
for(int i=0; i<SIZE-3; i++){
sum += Quiz[i].Score;
}
cout << sum << "\n";
sort(Quiz.begin(), Quiz.begin()+5, com2);
for(int i=0; i<SIZE-3; i++){
cout << Quiz[i].number <<" ";
}
return 0;
}
20.백준(5800) 성적 통계
- 정렬 기준에 대한 개념을 물어보는 문제이며 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main(void){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" , stdin);
int number = 0;
cin >> number;
int clase_number = 1;
while(number--){
int size =0;
cin >> size;
string str= "Class";
vector<int>V(size,0);
for(int i=0; i<size; i++){
cin >> V[i];
}
sort(V.rbegin(), V.rend());
int max_gap = V[0]-V[1];
for(int i=1; i<size-1; i++){
if(max_gap <V[i] - V[i+1]){
max_gap = V[i] - V[i+1];
}
}
cout << str << " " << clase_number++ <<"\n";
cout << "Max " << V[0] << ", Min " << V[size-1] <<", Largest gap " << max_gap <<"\n";
}
return 0;
}
21.백준(2161) 카드
- 자료구조 문제 -> 큐에 대한 개념을 물어보는 문제이다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int N = 0;
cin >> N;
queue<int>Q;
vector<int>V;
for(int i=1; i<=N; i++)
Q.push(i);
while(Q.size() !=1){
V.push_back(Q.front());
Q.pop();
int temp = Q.front();
Q.pop();
Q.push(temp);
}
for(auto v : V){
cout << v << " ";
}
cout << Q.front() <<"\n";
return 0;
}
22. 백준(14912) 숫자 빈도수
- 문자열 개념에 대한 문제이며 쉽게 해결이 가능하다.
#include <iostream>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt" , "r" ,stdin);
int n = 0;
cin >> n;
int target = 0;
cin >> target;
int answer = 0;
for(int i=1; i<=n; i++){
string str = to_string(i);
for(int j=0; j<str.length(); j++){
if(str[j] == target+48){
answer ++;
}
}
}
cout << answer << " " ;
return 0;
}
23. 백준(11292) 키 큰 사람
- 정렬과 구조체를 이용하면 쉽게 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
typedef struct TallMan{
string name;
string heigh;
}Tall;
bool com(Tall a, Tall b){
return a.heigh>b.heigh;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
while(1){
int number = 1;
cin >> number;
if(number ==0){return 0;}
vector<Tall>V;
for(int i=0; i<number; i++){
Tall T;
cin >> T.name >> T.heigh;
V.push_back(T);
}
sort(V.begin(), V.end(), com);
string answer = V[0].heigh;
cout << V[0].name << " ";
for(int i=1; i<number; i++){
if(answer == V[i].heigh){
cout << V[i].name << " ";
}
}
cout << "\n";
}
return 0;
}
24.백준(25325) 학생 인기도 측정
- Map을 이용하여 풀 수 있는 문제이다. Map을 사용하는건 어렵지 않지만 엔터까지 입력받기 Value값으로 정렬하기 이 2개가 어려웠던 문제였다.
- 엔터까지 입력받기
- getline(cin,변수)를 사용하면 된다. 단 버퍼를 제거하기 위해 cin이 들어간 코드 아래에 cin.ignore()함수를 사용해야 한다.
- Map을 Value값으로 정렬하기
- Map은 따로 Value값으로 정렬하는 함수를 제공하지 않는다 따라서 Map에 있는값을 Vector로 옮긴 후 조건에 맞게 정렬해야 한다.
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<string,int> Student;
bool com(Student A, Student B){
if(A.second == B.second){
return A.first < B.first;
}
else{
return A.second >B.second;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt","r", stdin);
int number = 0;
cin >> number;
cin.ignore();
map<string,int>M;
string name;
for(int i=0; i<number; i++){
cin >> name;
cin.ignore();
M.insert(make_pair(name,0));
}
string person;
string str;
for(int i=0; i<number; i++){
getline(cin,str);
int idx = 0;
person = "";
while(str[idx] != 0){
if(str[idx] !=' '){
person += str[idx];
idx++;
}
else{
M[person]++;
person = "";
idx++;
}
}
M[person]++;
}
vector<Student>V(M.begin(), M.end());
sort(V.begin(), V.end(),com);
for(auto v : V){
cout << v.first <<" " << v.second <<"\n";
}
return 0;
}
25.백준(14916) 학생 인기도 측정
- 다이나믹 프로그래밍과 백트래킹을 사용하면 쉽게 해결이 가능한 문제이다!
#include <iostream>
#include <vector>
#include <algorithm>
#define INF 2100000000
using namespace std;
vector<int>DP(100000,0);
vector<int>coins(2,0);
int Coins(int change);
int change;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
coins[0] = 5;
coins[1] = 2;
cin >> change;
int answer = Coins(change);
if(answer>=INF){
cout << -1 << "\n";
return 0;
}
cout << answer << "\n";
return 0;
}
int Coins(int change){
if(change<0)
return INF;
if(change ==0)
return 0;
if(DP[change]!=0)
return DP[change];
int min = INF;
for(int i=0;i<2; i++){
int temp = Coins(change-coins[i]);
if(temp<min){
min = temp;
}
}
DP[change] = min+1;
return DP[change];
}
26. 백준(17478) 재귀함수가 뭔가요?
- 재귀함수에 대한 기본 개념을 물어보는 문제로 쉽게 해결이 가능.
#include <iostream>
#include <string>
using namespace std;
void WhatIsRecursion(int number);
string str = "";
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int number =0 ;
cin >> number;
cout << "어느 한 컴퓨터공학과 학생이 유명한 교수님을 찾아가 물었다.\n";
WhatIsRecursion(number);
return 0;
}
void WhatIsRecursion(int number){
string line = str;
if(number==0){
cout << line << "\"재귀함수가 뭔가요?\"\n";
cout << line <<"\"재귀함수는 자기 자신을 호출하는 함수라네\"\n";
cout << line << "라고 답변하였지.\n";
}
else{
cout << line << "\"재귀함수가 뭔가요?\"\n";
cout << line << "\"잘 들어보게. 옛날옛날 한 산 꼭대기에 이세상 모든 지식을 통달한 선인이 있었어.\n";
cout << line << "마을 사람들은 모두 그 선인에게 수많은 질문을 했고, 모두 지혜롭게 대답해 주었지.\n";
cout << line << "그의 답은 대부분 옳았다고 하네. 그런데 어느 날, 그 선인에게 한 선비가 찾아와서 물었어.\"\n";
str += "____";
WhatIsRecursion(number-1);
cout << line << "라고 답변하였지.\n";
}
}
27.백준(2167) 2차원 배열의 합
- 반복문에 대한 기본개념만 있다면 해결 가능
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
void VectorP(vector<vector<int> >V, int N, int M);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin );
int N = 0;
int M = 0;
cin >> N >> M;
vector<vector<int> >V(N, vector<int>(M,0));
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
cin >> V[i][j];
}
}
int addCount = 0;
int X = 0;
int Y = 0;
cin >> addCount;
for(int i=0; i<addCount; i++){
cin >> N >> M >> X >> Y ;
int sum = 0;
for(int j=N-1; j<=X-1; j++){
for(int k=M-1; k<=Y-1; k++){
sum += V[j][k];
}
}
cout << sum << "\n";
}
}
void VectorP(vector<vector<int> >V, int N, int M){
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
cout << V[i][j] << " ";
}
cout << "\n";
}
}
28.백준(2167) 콘도 선정
- 구조체를 활용하여 해결 가능
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
void VectorP(vector<vector<int> >V, int N, int M);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin );
int N = 0;
int M = 0;
cin >> N >> M;
vector<vector<int> >V(N, vector<int>(M,0));
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
cin >> V[i][j];
}
}
int addCount = 0;
int X = 0;
int Y = 0;
cin >> addCount;
for(int i=0; i<addCount; i++){
cin >> N >> M >> X >> Y ;
int sum = 0;
for(int j=N-1; j<=X-1; j++){
for(int k=M-1; k<=Y-1; k++){
sum += V[j][k];
}
}
cout << sum << "\n";
}
}
void VectorP(vector<vector<int> >V, int N, int M){
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
cout << V[i][j] << " ";
}
cout << "\n";
}
}
29.백준(1094) 막대기
- 그리디 기법으로 가장 큰 수부터 비교하면서 해결
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int stick[7] = {64, 32, 16, 8, 4, 2, 1 };
int Stick(int target, int left , int right, int count);
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// 64 32 16 8 4 2 1
int targetLength = 0;
cin >> targetLength;
int answer = 0;
for(int i=0; i<7; i++){
if(stick[i]<=targetLength){
answer += targetLength/stick[i];
targetLength = targetLength%stick[i];
}
}
cout << answer << "\n";
}
30.백준(1789) 수들의 합
- 그리디 기법으로 1부터 하나의 증가하면서 값을 비교하면서 해결
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
ll S = 0;
cin >> S;
ll i = 1; //현재 n의 값
ll answer = 0; // 총합
int cnt = 0;
while (1){
answer += i; // 현재값 더하기 다음값
if(answer>S){break;} // 정답을 넘어서면 멈춤
cnt ++; // 정답을 넘어서지 않았다면 카운트 1 증가
i++; // n값 증가
}
cout << cnt << "\n";
return 0;
}
31.백준(2941) 크로아티나 알파벳
- string 라이브러리를 사용하면 해결이 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" , stdin);
vector<string>V(8);
V[0] = "c=";
V[1] = "c-";
V[2] = "dz=";
V[3] = "d-";
V[4] = "lj";
V[5] = "nj";
V[6] = "s=";
V[7] = "z=";
string alpha;
cin >> alpha;
int idx =0 ;
// ljes=njak
for(int i = 0; i < V.size(); i++)
{
while(1){
idx = alpha.find(V[i]);
if(idx == string::npos)
break;
alpha.replace(idx,V[i].length(),"#");
}
}
cout << alpha.length();
return 0;
}
32.백준(9655) 돌 게임
- 그리디 기법으로 3개를 가져올 수 있으면 무조건 3개를 가져오고 그게 아니면 1개를 가져오는 방식으로 해결이 가능하다.
#include <iostream>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
int number = 0;
cin >> number;
bool flag = true; // sk
while(number>0)
{
if(number>=3){
number = number -3;
if(flag == true)
flag = false;
else
flag = true;
}
else
{
number --;
if(flag == true)
flag = false;
else
flag = true;
}
}
if(flag == false){
cout << "SK" << "\n";
}
else{
cout << "CY" << "\n";
}
return 0;
}
33. 백준(8979) 올림픽
- 구조체를 만들어 정렬하면 쉽게 해결이 가능하다. 정렬이 없어도 상관없음
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct Rank{
int country;
int gold;
int silver;
int bronze;
int rank;
}Rank;
bool com(Rank a, Rank b)
{
return a.country <= b.country;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input.txt", "r", stdin);
int numOfCountry = 0;
int targetRank = 0;
cin >> numOfCountry >> targetRank;
vector<Rank>R(numOfCountry);
for(int i=0; i<numOfCountry; i++)
{
cin >> R[i].country >> R[i].gold >> R[i].silver >> R[i].bronze;
}
for(int i=0; i<numOfCountry; i++){
int rnakNum = 1;
for(int j=0; j<numOfCountry; j++){
if(i==j)
continue;
else
{
if(R[i].gold < R[j].gold) //금메달이 나보다 많은 사람이 있다면 순위에서 밀림
rnakNum++;
else if(R[i].gold == R[j].gold){ //금메달이 같다면
if(R[i].silver < R[j].silver) //은메달이 나보다 많은 사람이 있다면 순위에서 밀림
rnakNum++;
else if(R[i].silver == R[j].silver){ //은메달이 같다면
if(R[i].bronze <R[j].bronze) //동메달이 나보다 많은 사람이 있다면 순위에서 밀림
rnakNum ++;
}
}
}
}
R[i].rank = rnakNum;
}
sort(R.begin(), R.end(), com); //이건 필요없을듯
// for(int i=0; i<numOfCountry; i++){
// cout << R[i].country << " " << R[i].gold << " " << R[i].silver << " " << R[i].bronze << " " << R[i].rank <<"\n";
// }
for(int i=0; i<numOfCountry; i++)
if(R[i].country == targetRank)
cout << R[i].rank << "\n";
return 0;
}
———————-
백준_브론즈
백준_브론즈_1
1. 백준(1546) 평균
세준이는 기말고사를 망쳤다. 세준이는 점수를 조작해서 집에 가져가기로 했다. 일단 세준이는 자기 점수 중에 최댓값을 골랐다. 이 값을 M이라고 한다. 그리고 나서 모든 점수를 점수/M100으로 고쳤다. 예를 들어, 세준이의 최고점이 70이고, 수학점수가 50이었으면 수학점수는 50/70100이 되어 71.43점이 된다. 세준이의 성적을 위의 방법대로 새로 계산했을 때, 새로운 평균을 구하는 프로그램을 작성하시오.
-입력
첫째 줄에 시험 본 과목의 개수 N이 주어진다. 이 값은 1000보다 작거나 같다. 둘째 줄에 세준이의 현재 성적이 주어진다. 이 값은 100보다 작거나 같은 음이 아닌 정수이고, 적어도 하나의 값은 0보다 크다.
-출력
첫째 줄에 새로운 평균을 출력한다. 실제 정답과 출력값의 절대오차 또는 상대오차가 10-2 이하이면 정답이다.
#include <stdio.h>
#include <stdlib.h>
int main(){
int N ;
scanf("%d", &N);
float arr[N];
int max = 0;
float mean = 0;
for(int i =0; i<N; i++){
scanf("%f", &arr[i]);
}
max = arr[0];
for(int i =1 ;i <N; i++){
if(max <= arr[i]){max = arr[i];}
}
for(int i=0; i<N; i++){
arr[i] = arr[i]/max*100;
mean += arr[i];
}
mean = mean / N;
printf("%.2f", mean);
return 0;
}
2.백준(4344) 평균은 넘겠지
대학생 새내기들의 90%는 자신이 반에서 평균은 넘는다고 생각한다. 당신은 그들에게 슬픈 진실을 알려줘야 한다.
-입력
첫째 줄에는 테스트 케이스의 개수 C가 주어진다. 둘째 줄부터 각 테스트 케이스마다 학생의 수 N(1 ≤ N ≤ 1000, N은 정수)이 첫 수로 주어지고, 이어서 N명의 점수가 주어진다. 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다.
-출력
각 케이스마다 한 줄씩 평균을 넘는 학생들의 비율을 반올림하여 소수점 셋째 자리까지 출력한다.
#include <stdio.h>
#include <stdlib.h>
int main(void){
int testcase ;
float mean = 0;
int cnt = 0;
scanf("%d", &testcase);
for(int i=0; i<testcase; i++){
int student = 0;
cnt = 0;
mean = 0;
scanf("%d", &student);
int arr[student];
for(int j=0; j<student; j++){
scanf("%d", &arr[j]);
mean += arr[j];
}
mean = mean/student;
for(int j=0; j<student; j++){
if(mean <arr[j])
cnt ++;
} // for_jj
mean = (float)cnt / student;
mean = mean * 100;
printf("%.3f%%\n", mean);
} //for_i
return 0;
}
3.백준(1157) 단어 공부
알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.
-입력
첫째 줄에 알파벳 대소문자로 이루어진 단어가 주어진다. 주어지는 단어의 길이는 1,000,000을 넘지 않는다.
-출력
첫째 줄에 이 단어에서 가장 많이 사용된 알파벳을 대문자로 출력한다. 단, 가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_SIZE 1000000
int main(){
int len = 0;
char str[MAX_SIZE];
int alpha[26] = {0};
int temp = 0;
int max = 0;
char ans[1];
int cnt = 0;
scanf("%s", str);
len = strlen(str);
for(int i=0; i<len; i++)
if (str[i] >= 65 && str[i] <= 90) { str[i] = str[i] + 32; } //대문자를 소문자로
for(int i=0; i<len; i++){
temp = str[i]-97;
alpha[temp]++;
} // 각 알파벳이 나온 빈도 체크
for(int i=0; i<26; i++){
if(max <= alpha[i]) {
max = alpha[i];
ans[0] = i+97;
} //가장 많이 나온 알파벳 체크
}
for(int i=0; i<26; i++){
if(max == alpha[i]) {cnt++;} // 최대가 중복이면 ?출력
}
if(cnt >1){ printf("?\n");}
else{
printf("%c\n", ans[0]-32);
} //그게 아닐경우 대문자 출력
return 0;
}
4.백준(2750) 수 정렬하기
N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.
-입력
첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수 주어진다. 이 수는 절댓값이 1,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.
-출력
첫째 줄부터 N개의 줄에 오름차순으로 정렬한 결과를 한 줄에 하나씩 출력한다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
void sort(int arr[], int N){
int temp = 0;
for(int i=0; i<N; i++){
for(int j= i+1; j<N; j++){
if(arr[i]>arr[j]){
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
} //배열을 돌면서 맨 앞부터 비교하면서 스왑해주기
else continue;
}
}//for_i
for(int i=0; i<N; i++){
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void){
int N;
scanf("%d",&N);
int arr[N];
for(int i=0; i<N; i++){
scanf("%d", &arr[i]);
}
sort(arr,N);
return 0;
}
5.백준(2740) 행렬 곱
NM크기의 행렬 A와 MK크기의 행렬 B가 주어졌을 때, 두 행렬을 곱하는 프로그램을 작성하시오.
-입력
첫째 줄에 행렬 A의 크기 N 과 M이 주어진다. 둘째 줄부터 N개의 줄에 행렬 A의 원소 M개가 순서대로 주어진다. 그 다음 줄에는 행렬 B의 크기 M과 K가 주어진다. 이어서 M개의 줄에 행렬 B의 원소 K개가 차례대로 주어진다. N과 M, 그리고 K는 100보다 작거나 같고, 행렬의 원소는 절댓값이 100보다 작거나 같은 정수이다.
-출력
첫째 줄부터 N개의 줄에 행렬 A와 B를 곱한 행렬을 출력한다. 행렬의 각 원소는 공백으로 구분한다.
#include <stdio.h>
#include <stdlib.h>
int main(){
int N,M,K;
int sum = 0;
scanf("%d %d",&N,&M);
int matrix1[N][M];
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
scanf("%d",&matrix1[i][j]);
}
} //A 행렬 입력
scanf("%d %d",&M,&K);
int matrix2[M][K];
for(int i=0; i<M; i++){
for(int j=0; j<K; j++){
scanf("%d",&matrix2[i][j]);
}
} // B 행렬 입력
int matrix3[N][K];
for(int i=0; i<N; i++){ //A행렬의 행만큼
for(int j=0; j<K; j++){ //B행렬의 열만큼
for(int k=0; k<M; k++){ // A행렬의 열 == B행렬의 행 만큼
sum += matrix1[i][k] * matrix2[k][j];
}
matrix3[i][j] = sum;
sum = 0;
}
}
for(int i=0; i<N; i++){
for(int j=0; j<K; j++){
printf("%d ",matrix3[i][j]);
}
printf("\n");
}
return 0;
}
6. 백준(1110) 더하기사이클
0보다 크거나 같고, 99보다 작거나 같은 정수가 주어질 때 다음과 같은 연산을 할 수 있다. 먼저 주어진 수가 10보다 작다면 앞에 0을 붙여 두 자리 수로 만들고, 각 자리의 숫자를 더한다. 그 다음, 주어진 수의 가장 오른쪽 자리 수와 앞에서 구한 합의 가장 오른쪽 자리 수를 이어 붙이면 새로운 수를 만들 수 있다. 다음 예를 보자. 26부터 시작한다. 2+6 = 8이다. 새로운 수는 68이다. 6+8 = 14이다. 새로운 수는 84이다. 8+4 = 12이다. 새로운 수는 42이다. 4+2 = 6이다. 새로운 수는 26이다. 위의 예는 4번만에 원래 수로 돌아올 수 있다. 따라서 26의 사이클의 길이는 4이다. N이 주어졌을 때, N의 사이클의 길이를 구하는 프로그램을 작성하시오.
-입력
첫째 줄에 N이 주어진다. N은 0보다 크거나 같고, 99보다 작거나 같은 정수이다.
-출력
첫째 줄에 N의 사이클 길이를 출력한다.
#include <iostream>
#include <string>
using namespace std;
int main(){
int N;
int temp = 0;
int sum = 0;
int cnt = 0;
int one ;
int ten;
cin >> N;
int check = N;
if(N==0){cnt =1; cout << cnt ; return 0 ;}
//cout << 68 %10; // 1의 자리
//cout << 68 /10; // 10의 자리
else{
while(check!=temp){
one = N%10;
ten = N/10;
sum = one + ten;
temp = one*10 + sum%10;
cnt++;
N=temp;
} // while
}
cout << cnt;
return 0;
}
7. 백준(2309) 일곱난쟁이
왕비를 피해 일곱 난쟁이들과 함께 평화롭게 생활하고 있던 백설공주에게 위기가 찾아왔다. 일과를 마치고 돌아온 난쟁이가 일곱 명이 아닌 아홉 명이었던 것이다. 아홉 명의 난쟁이는 모두 자신이 “백설 공주와 일곱 난쟁이”의 주인공이라고 주장했다. 뛰어난 수학적 직관력을 가지고 있던 백설공주는, 다행스럽게도 일곱 난쟁이의 키의 합이 100이 됨을 기억해 냈다. 아홉 난쟁이의 키가 주어졌을 때, 백설공주를 도와 일곱 난쟁이를 찾는 프로그램을 작성하시오.
-입력
아홉 개의 줄에 걸쳐 난쟁이들의 키가 주어진다. 주어지는 키는 100을 넘지 않는 자연수이며, 아홉 난쟁이의 키는 모두 다르며, 가능한 정답이 여러 가지인 경우에는 아무거나 출력한다.
-출력
일곱 난쟁이의 키를 오름차순으로 출력한다. 일곱 난쟁이를 찾을 수 없는 경우는 없다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// 전체 합 - 두 명의 난쟁이 = 100을 찾는다.
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N = 9;
int sum = 0;
vector<int>ans(N,0);
int del1 = 0;
int del2 = 0;
for(int i=0; i<N; i++){
cin >> ans[i];
sum = sum+ans[i];
} //모든 난쟁이의 합
for(int i=0; i<N; i++){
for(int j=i+1; j<N; j++){
int check = ans[i] + ans[j];
if(((sum - check) == 100)){ //총합 - 두 명의 합 == 100인 Index를 찾아 인덱스를 저장 후 종료
del1 = i;
del2 = j;
break;
}
}
}
ans.erase(ans.begin() + del1); // 원소 삭제
ans.erase(ans.begin() + del2-1); //위에서 한 번 삭제했으므로 길이가 1 줄어들었음
sort(ans.begin(), ans.end()); //오름차순 정렬
for(vector<int>::iterator it = ans.begin(); it!=ans.end(); it++){
cout << *it <<"\n";
}
return 0;
}
8. 백준(2748) 피보나치 수2
피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다. 이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가 된다. n=17일때 까지 피보나치 수를 써보면 다음과 같다. 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597 n이 주어졌을 때, n번째 피보나치 수를 구하는 프로그램을 작성하시오.
-입력
첫째 줄에 n이 주어진다. n은 90보다 작거나 같은 자연수이다.
-출력
첫째 줄에 n번째 피보나치 수를 출력한다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<long long>ans(100,0);
long long fib(int N){
if(N<=1)
return N;
else{
long long idx = N-2;
if(ans[idx]==0){
ans[idx] = fib(N-2) +fib(N-1);
return ans[idx];
}
else{
return ans[idx];
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
cout << fib(N);
return 0;
}
9. 백준(2893) 설탕배달
상근이는 요즘 설탕공장에서 설탕을 배달하고 있다. 상근이는 지금 사탕가게에 설탕을 정확하게 N킬로그램을 배달해야 한다. 설탕공장에서 만드는 설탕은 봉지에 담겨져 있다. 봉지는 3킬로그램 봉지와 5킬로그램 봉지가 있다.상근이는 귀찮기 때문에, 최대한 적은 봉지를 들고 가려고 한다. 예를 들어, 18킬로그램 설탕을 배달해야 할 때, 3킬로그램 봉지 6개를 가져가도 되지만, 5킬로그램 3개와 3킬로그램 1개를 배달하면, 더 적은 개수의 봉지를 배달할 수 있다. 상근이가 설탕을 정확하게 N킬로그램 배달해야 할 때, 봉지 몇 개를 가져가면 되는지 그 수를 구하는 프로그램을 작성하시오.
-입력
첫째 줄에 N이 주어진다. (3 ≤ N ≤ 5000)
-출력
상근이가 배달하는 봉지의 최소 개수를 출력한다. 만약, 정확하게 N킬로그램을 만들 수 없다면 -1을 출력한다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int sugar5;
int r = 0;
int N = 0;
cin >> N;
sugar5 = N / 5;
r = N%5;
if(r==0) // 5로 다 나뉘어진다면 바로 출력
cout << sugar5;
else if (r==1 && sugar5>=1){ //5로 나누었을 때 1이 남는다면 그 전 5개봉지를 1개빼고 5+1 -> 3개 봉지 2개로 나눈다.
cout << sugar5 -1 + 2 << "\n";
}
else if (r==2 && sugar5>=2) { //5로 나누었을 때 2가 남는다면 그 전 5개봉지를 2개 빼고 10+2 -> 3개 봉지 4개로 나눈다.
cout << sugar5 -2 + 4 << "\n";
}
else if (r==3 ){ //5로 나누었을 때 3이 남는다면 3개봉지 1개만을 추가해주면 된다.
cout << sugar5 + 1 <<"\n";
}
else if (r==4 && sugar5>=1){ //5로 나누었을 때 4가 남는다면 5개봉지를 1개 빼고 5+4 -> 3개 봉지 3개로 나누다.
cout << sugar5-1 +3 <<"\n";
}
else { // 그 이외에 경우는 모두 -1로 처리한다.
cout << -1 << "\n";
}
return 0;
}
10. 백준(2775) 부녀회장이 될테야
평소 반상회에 참석하는 것을 좋아하는 주희는 이번 기회에 부녀회장이 되고 싶어 각 층의 사람들을 불러 모아 반상회를 주최하려고 한다. 이 아파트에 거주를 하려면 조건이 있는데, “a층의 b호에 살려면 자신의 아래(a-1)층의 1호부터 b호까지 사람들의 수의 합만큼 사람들을 데려와 살아야 한다” 는 계약 조항을 꼭 지키고 들어와야 한다. 아파트에 비어있는 집은 없고 모든 거주민들이 이 계약 조건을 지키고 왔다고 가정했을 때, 주어지는 양의 정수 k와 n에 대해 k층에 n호에는 몇 명이 살고 있는지 출력하라. 단, 아파트에는 0층부터 있고 각층에는 1호부터 있으며, 0층의 i호에는 i명이 산다.
-입력
첫 번째 줄에 Test case의 수 T가 주어진다. 그리고 각각의 케이스마다 입력으로 첫 번째 줄에 정수 k, 두 번째 줄에 정수 n이 주어진다
-출력
각각의 Test case에 대해서 해당 집에 거주민 수를 출력하라.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int testCase;
cin >> testCase;
while(testCase--)
{
int Num = 1;
int K, N;
cin >> K >> N;
vector<int>ans(N,0);
for(int i=0; i<N; i++)
ans[i] = i+1; //제일 아랫층 셋팅
for(int i=1; i<=K; i++)
{
for(int j=1; j<=N; j++)
{
if(j==1){continue;} // 각 층의 1호사람들은 1명으로 고정
else{
ans[j-1]+= ans[j-2]; //그게 아니라면 자신부터 그 전층의 사람까지 모두 더해준다
}
}
}
cout << ans[N-1]<<"\n";
}
return 0;
}
11. 백준(11719) 그대로 출력하기 2
입력 받은 대로 출력하는 프로그램을 작성하시오.
-입력
입력이 주어진다. 입력은 최대 100줄로 이루어져 있고, 알파벳 소문자, 대문자, 공백, 숫자로만 이루어져 있다. 각 줄은 100글자를 넘지 않으며, 빈 줄이 주어질 수도 있고, 각 줄의 앞 뒤에 공백이 있을 수도 있다.
-출력
입력받은 그대로 출력한다.
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
string str;
int testCase = 100;
while(testCase--)
{
getline(cin, str);
cout << str << "\n";
}
return 0;
}
12. 백준(11050) 이항계수 1
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int factorial(int n){
if(n<=1){
return 1;
}
else{
return factorial(n-1)*n;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n , k;
cin >> n >> k;
if(k==0){cout << 1 <<"\n"; return 0;}
if(k>n){return 0;}
cout << factorial(n) / (factorial(k) * factorial(n-k)) << "\n";
return 0;
}
13. 백준(1032) 명령 프롬프트
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int Num = 0;
cin >> Num;
bool check = false;
string str[Num];
string answer = "";
for(int i=0; i<Num; i++)
cin >> str[i];
if(Num == 1){
answer = str[0];
cout << answer << "\n";
return 0;
}
// N이 1인경우 예외조건
for(int i=0; i<str[0].length(); i++){
char temp = str[0][i];
for(int j=1; j<Num; j++){
if(temp == str[j][i]){
check = true;
}
else{check = false; break;}
}
if(check == true){
answer += temp;
check = false;
// 모두 일치한다면 추가
}
else{answer += '?';}
// 하나라도 다르다면 ? 추가
}
cout << answer << "\n";
return 0;
}
14. 백준(9946) 단어 퍼즐
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin);
string a;
string b;
cin >> a >> b;
int idx = 1;
while(a!="END" && b!="END"){
sort(a.begin(), a.end());
sort(b.begin(), b.end());
if(a==b){
cout << "Case " << idx << ": " << "same\n";
}
else{
cout << "Case " << idx << ": " << "different\n";
}
idx++;
cin >> a >> b;
}
return 0;
}
15. 백준(18766) 카드 바꿔치기
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main(void){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int test_case = 0;
cin >> test_case;
bool check = false;
while(test_case--){
int card = 0 ;
cin >> card;
vector<string>A_cards(card);
vector<string>B_cards(card);
for(int i=0; i<card; i++)
cin >> A_cards[i];
for(int i=0; i<card; i++)
cin >> B_cards[i];
sort(A_cards.begin(), A_cards.end());
sort(B_cards.begin(), B_cards.end());
for(int i=0; i<card; i++){
if(A_cards[i] != B_cards[i])
{ check = true;
break;
}
}
if(check==true){check = false; cout << "CHEATER\n";}
else {cout << "NOT CHEATER\n";}
}
return 0;
}
16. 백준(15819) 너의 핸들은
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main(void){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int VectorSize = 0;
int TargetNumber = 0;
cin >> VectorSize >> TargetNumber;
vector<string>V(VectorSize);
for(int i=0; i<VectorSize; i++)
cin >> V[i];
sort(V.begin(), V.end());
cout << V[TargetNumber-1] <<"\n";
return 0;
}
17. 백준(23899) 알고리즘 수업 - 선택 정렬 5
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt","r",stdin);
int N =0;
cin >> N ;
vector<int>Arr1(N,0);
vector<int>Arr2(N,0);
for(int i=0; i<N; i++)
cin >> Arr1[i];
for(int i=0; i<N; i++)
cin >> Arr2[i];
if(Arr1 == Arr2){
cout << 1 ;
return 0;
}
int cnt = 0;
for(int i=0; i<N; i++){
int Max = Arr1[0]; // 기준 값 정하기
int Idx = 0;
for(int j=1; j<N-i; j++){
if(Max<=Arr1[j]){
Max = Arr1[j];
Idx = j;
}
}
// 스왑이 일어나지 않은경우는 카운트를 세지 않으므로 예외
int temp = Arr1[N-i-1];
Arr1[N-i-1] = Arr1[Idx];
Arr1[Idx] = temp;
if(Arr1 == Arr2){
cout << 1 ;
return 0;
}
}
cout << 0 ; // 끝날 때 까지 타겟넘버가 안된다면
return 0;
}
18. 백준(17224) APC는 왜 서브태스크 대회가 되었을까?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct subtask{
int sub1;
int sub2;
}subtask;
bool com(subtask a, subtask b){
return a.sub2 < b.sub2;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
int number = 0; // 문제 갯수
int task = 0; // 풀 수 있는 난이도
int possible =0; //풀 수 있는 문제 수
cin >> number >> task >> possible;
if(possible==0){
cout << 0 ;
return 0;
} // 문제를 하나도 못푸는 경우 예외처리
vector<subtask>Apc;
for(int i=0; i<number; i++){
subtask s;
cin >> s.sub1 >> s.sub2;
Apc.push_back(s);
} //sub task 입력
sort(Apc.begin(), Apc.end(), com); // sub2를 기준으로 오름차순 정렬
int sum = 0; //총 합
int cnt = 0; // 푼 문제 수
for(int i=0; i<number; i++){
if(Apc[i].sub2<=task){ //만약 더 높은 점수를 주는 sub2를 풀 수 있다면 풀고 점수, 푼 문제수 추가
sum = sum + 140;
cnt ++;
}
else{ // sub2를 못 푼다면
if(Apc[i].sub1<=task){ // sub1을 풀 수 있는지 확인 후 풀 수 있다면 점수, 푼 문제수 추가
sum =sum +100;
cnt ++;
}
}
if(cnt == possible){break;} // 풀 수 있는 문제를 다 풀었다면 종료
}
cout << sum ; // 총합 출력
return 0;
}
19. 백준(6996) 애너그램
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt","r",stdin);
int testCase = 0;
cin >> testCase;
while(testCase--){
string a,b;
string tempA, tempB;
cin >> a >> b;
tempA = a;
tempB = b;
sort(tempA.begin(), tempA.end());
sort(tempB.begin(), tempB.end());
if(tempA == tempB){
cout << a << " & " << b << " are anagrams.\n";
}
else{
cout << a << " & " << b << " are NOT anagrams.\n";
}
}
return 0;
}
20. 백준(4796) 캠핑
그리디로 해결 가능한 문제
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r" ,stdin);
int L,P,V;
cin >> L >> P >> V;
/*
캠핑장을 연속하는 P일 중, L일동안만 사용할 수 있다. 강산이는 이제 막 V일짜리 휴가를 시작했다. 강산이가 캠핑장을 최대 며칠동안 사용할 수 있을까? (1 < L < P < V)
*/
int cnt = 1;
while(1){
if(L==0 && P==0 && V==0)
break;
int answer = 0;
while(V>P){
V = V-P;
answer = answer + L;
}
if(V>=L){
answer = answer + L;
}
else{
answer = answer + V;
}
cout << "Case " << cnt++ << ":" << " " <<answer <<"\n";
cin >> L >> P >> V;
}
return 0;
}
———————-
백준_브론즈_2
1. 백준(2562) 최댓값
9개의 서로 다른 자연수가 주어질 때, 이들 중 최댓값을 찾고 그 최댓값이 몇 번째 수인지를 구하는 프로그램을 작성하시오.
예를 들어, 서로 다른 9개의 자연수
3, 29, 38, 12, 57, 74, 40, 85, 61
이 주어지면, 이들 중 최댓값은 85이고, 이 값은 8번째 수이다.
-입력
첫째 줄부터 아홉 번째 줄까지 한 줄에 하나의 자연수가 주어진다. 주어지는 자연수는 100 보다 작다.
-출력
첫째 줄에 최댓값을 출력하고, 둘째 줄에 최댓값이 몇 번째 수인지를 출력한다.
#include <stdio.h>
#include <stdlib.h>
int main(){
int n = 9;
int arr[n];
int idx = 1;
for(int i=0; i<n; i++){
scanf("%d",&arr[i]);
}
int max = arr[0];
idx = 1;
for(int i=1; i<n; i++){
if(max <= arr[i]){
max = arr[i];
idx = i+1;
}
}
printf("%d\n", max);
printf("%d\n", idx);
return 0;
}
2. 백준(10809) 알파벳 찾기
알파벳 소문자로만 이루어진 단어 S가 주어진다. 각각의 알파벳에 대해서, 단어에 포함되어 있는 경우에는 처음 등장하는 위치를, 포함되어 있지 않은 경우에는 -1을 출력하는 프로그램을 작성하시오..
-입력
첫째 줄에 단어 S가 주어진다. 단어의 길이는 100을 넘지 않으며, 알파벳 소문자로만 이루어져 있다.
-출력
각각의 알파벳에 대해서, a가 처음 등장하는 위치, b가 처음 등장하는 위치, … z가 처음 등장하는 위치를 공백으로 구분해서 출력한다.만약, 어떤 알파벳이 단어에 포함되어 있지 않다면 -1을 출력한다. 단어의 첫 번째 글자는 0번째 위치이고, 두 번째 글자는 1번째 위치이다
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int main(){
char str[101];
int alpha[26];
int check = 0;
for(int i=0; i<26; i++){
alpha[i] = -1;
}
int i = 0;
int temp = 0;
scanf("%s", str);
int len = strlen(str);
while(len--){
temp = str[i] - 97;
if(alpha[temp] == -1){
alpha[temp] =i;
i++;
} // 처음 나온 알파벳이면 idx 저장
else{ //중복 처리
i++;
continue;
}
} //while
for(int i=0; i<26; i++){
printf("%d ", alpha[i]);
}
printf("\n");
return 0;
}
3.백준(1152) 단어의 개수
영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열에는 몇 개의 단어가 있을까? 이를 구하는 프로그램을 작성하시오. 단, 한 단어가 여러 번 등장하면 등장한 횟수만큼 모두 세어야 한다.
-입력
첫 줄에 영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열의 길이는 1,000,000을 넘지 않는다. 단어는 공백 한 개로 구분되며, 공백이 연속해서 나오는 경우는 없다. 또한 문자열은 공백으로 시작하거나 끝날 수 있다.
-출력
첫째 줄에 단어의 개수를 출력한다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_SIZE 1000000
int main(void){
int i, len;
int cnt = 1;
char str[MAX_SIZE];
scanf("%[^\n]", str);
len = strlen(str);
if(len == 1) {
if(str[0] == ' ') {
printf("0\n");
return 0;
}
}
for(i = 1; i < len-1; i++) {
if(str[i] == ' ')
cnt++;
}
printf("%d\n", cnt);
return 0;
}
4.백준(8958) OX퀴즈
“OOXXOXXOOO”와 같은 OX퀴즈의 결과가 있다. O는 문제를 맞은 것이고, X는 문제를 틀린 것이다. 문제를 맞은 경우 그 문제의 점수는 그 문제까지 연속된 O의 개수가 된다. 예를 들어, 10번 문제의 점수는 3이 된다. “OOXXOXXOOO”의 점수는 1+2+0+0+1+0+0+1+2+3 = 10점이다. OX퀴즈의 결과가 주어졌을 때, 점수를 구하는 프로그램을 작성하시오.
-입력
첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 길이가 0보다 크고 80보다 작은 문자열이 주어진다. 문자열은 O와 X만으로 이루어져 있다.
-출력
각 테스트 케이스마다 점수를 출력한다.
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
int main(){
int N;
cin >> N;
int cnt = 0;
int sum = 0;
int *arr = new int[N];
string str;
for(int i=0; i<N; i++){
cin >> str;
for(int j=0; j<str.length(); j++){
if(str[j]=='O'){cnt++; sum = cnt+sum; }
else{cnt = 0;}
}
arr[i]=sum;
sum = 0;
cnt = 0;
}
for(int i=0; i<N ;i++){
cout << arr[i]<<endl;
}
return 0;
}
5.백준(11720) 숫자의 합
N개의 숫자가 공백 없이 쓰여있다. 이 숫자를 모두 합해서 출력하는 프로그램을 작성하시오.
-입력
첫째 줄에 숫자의 개수 N (1 ≤ N ≤ 100)이 주어진다. 둘째 줄에 숫자 N개가 공백없이 주어진다.
-출력
입력으로 주어진 숫자 N개의 합을 출력한다.
#include<stdio.h>
int main(){
int n, sum = 0;
scanf("%d", &n);
char arr[n];
scanf("%s", &arr);
for(int i = 0; i < n; i++){
sum += arr[i] - '0';
}
printf("%d", sum);
}
6.백준(3052) 나머지
두 자연수 A와 B가 있을 때, A%B는 A를 B로 나눈 나머지 이다. 예를 들어, 7, 14, 27, 38을 3으로 나눈 나머지는 1, 2, 0, 2이다. 수 10개를 입력받은 뒤, 이를 42로 나눈 나머지를 구한다. 그 다음 서로 다른 값이 몇 개 있는지 출력하는 프로그램을 작성하시오.
-입력
첫째 줄부터 열번째 줄 까지 숫자가 한 줄에 하나씩 주어진다. 이 숫자는 1,000보다 작거나 같고, 음이 아닌 정수이다.
-출력
첫째 줄에, 42로 나누었을 때, 서로 다른 나머지가 몇 개 있는지 출력한다.
#include <iostream>
#include <algorithm>
#include <vector>
#define N 10;
using namespace std;
int main(){
int it = N;
vector<int> arr;
vector<int>::iterator iter = arr.begin();
while(it!=0){
int Number = 0;
cin >> Number;
arr.push_back(Number%42);
it--;
}
sort(arr.begin(), arr.end()); //정렬
arr.erase( unique(arr.begin(), arr.end() ), arr.end());// 중복값 제거 정렬 후 사용하여야 함
cout << arr.size() << endl; // 벡터의 사이즈를 리턴
return 0;
}
7.백준(2675) 문자열 반복
문자열 S를 입력받은 후에, 각 문자를 R번 반복해 새 문자열 P를 만든 후 출력하는 프로그램을 작성하시오. 즉, 첫 번째 문자를 R번 반복하고, 두 번째 문자를 R번 반복하는 식으로 P를 만들면 된다. S에는 QR Code “alphanumeric” 문자만 들어있다. QR Code “alphanumeric” 문자는 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$%*+-./: 이다.
-입력
첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 1,000)가 주어진다. 각 테스트 케이스는 반복 횟수 R(1 ≤ R ≤ 8), 문자열 S가 공백으로 구분되어 주어진다. S의 길이는 적어도 1이며, 20글자를 넘지 않는다.
-출력
각 테스트 케이스에 대해 P를 출력한다.
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
int main(){
int testCase =0 ;
cin >> testCase;
while(testCase--){
vector<char>answer; // char 벡터 생성
vector<char>::iterator iter = answer.begin();
int it = 0;
cin >> it; // 2
string str ;
cin >> str; //ABC
int len = str.length();
//cout << " str is " << str << " " << "len is " << len << endl;
for(int i=0; i<len; i++){ //문자열의 길이만큼 반복
for(int j=0; j<it; j++){ //주어진 횟수만큼 반복하여 추가
answer.push_back(str[i]);
}
}
for(iter=answer.begin(); iter!=answer.end(); iter++){
cout << *iter ; //출력
}
cout << endl;
}
return 0;
}
8.백준(10953) A+B-6
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int testCase = 0;
cin >> testCase;
int Sum =0;
string str;
while(testCase--){
cin >> str;
Sum = 0;
for(int i=0; i<3; i++){
if(str[i] == ','){
continue;
}
else{
Sum = Sum + str[i] - '0';
}
}
cout << Sum << "\n";
}
return 0;
}
9.백준(10808) 알파벳 개수
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
string str ;
cin >> str;
vector<int>alpha(26,0);
int len = str.length();
for(int i=0; i<len; i++){
alpha[str[i]-97] ++;
}
for(vector<int>::iterator it = alpha.begin(); it!=alpha.end();it++){
cout << *it << " " ;
}
cout << "\n";
return 0;
}
10.백준(2231) 분해합(
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int Sum(int n)
{
int sum = n;
while(n!=0)
{
sum += n%10;
n = n/10;
}
return sum;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
vector<int>answer;
bool check = false;
int n ;
cin >> n;
for(int i=2; i<n; i++)
{
int temp = Sum(i);
if(temp == n)
{
answer.push_back(i);
check = true;
}
}
if(check == true)
{
sort(answer.begin(), answer.end());
cout << answer[0] <<"\n";
}
else
cout << 0 << "\n";
return 0;
}
11.백준(2292) 벌집(
#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;
// 벌집
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int cnt = 1;
int Pow = 2;
// 중앙1에서부터
// 3 * 2*i
int Num = 0;
cin >> Num;
Num = Num-1;
while(Num>0)
{
Num = Num - 3*Pow;
Pow += 2;
cnt ++;
}
cout << cnt ;
return 0;
}
12.백준(2798) 블랙잭
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N, M;
int Sum = 0;
cin >> N >> M;
vector<int>ans(N,0);
for(int i=0; i<N; i++)
{
cin >> ans[i];
Sum += ans[i];
}
sort(ans.begin(), ans.end());
int answer = 0;
int black = 0;
int min = 210000000 ;
int card = 0;
for(int i=0; i<N; i++){
for(int j=i+1; j<N; j++){
for(int k=j+1; k<N; k++){
answer = ans[i] + ans[j]+ ans[k];
if(answer >M){continue;}
black = abs(answer-M);
if(min>=black){
min = black;
card = answer;
}
}
}
}
cout << card << "\n";
return 0;
}
13.백준(5622) 다이얼
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int phone(char str){
switch(str){
case 'A' : case 'B' : case 'C':
return 2;
case 'D' : case 'E' : case 'F':
return 3;
case 'G' : case 'H' : case 'I':
return 4;
case 'J' : case 'K' : case 'L':
return 5;
case 'M' : case 'N' : case 'O':
return 6;
case 'P' : case 'Q' : case 'R': case 'S':
return 7;
case 'T' : case 'U' : case 'V':
return 8;
case 'W' : case 'X' : case 'Y': case 'Z':
return 9;
}
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
string str;
int ans = 0;
cin >> str;
int len = str.length();
vector<int>v (len, 0);
for(int i=0; i<len; i++){
v[i] = phone(str[i]);
ans = ans+v[i]+1;
}
cout << ans << "\n";
return 0;
}
14.백준(2902) KMP는 왜 KMP일까?
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(){
string str;
cin >> str;
int len = str.length();
for(int i=0; i<len; i++){
if(str[i] >='A' && str[i] <='Z')
{cout << str[i];}
}
cout << "\n";
return 0;
}
15.백준(15829) Hashing
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
long long r = 1;
long long Mod = 1234567891;
int len = 0;
cin >> len;
string str ;
cin >> str;
long long answer = 0;
for(int i=0; i<len; i++){
long long temp = str[i]-96;
temp = temp * r;
answer += temp;
r *=31;
r = r % Mod;
}
answer = answer % Mod;
cout << answer <<"\n";
return 0;
}
16.백준(2605) 줄 세우기
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int Student = 0 ;
cin >> Student;
vector<int>ans(Student);
for(int i=1; i<=Student; i++){
int com = 0;
cin >> com;
ans.insert(ans.begin()+com, i);
}
// 주어진 위치에 insert
for(int i = Student-1; i>=0; i--)
cout << ans[i] << " ";
cout << "\n";
return 0;
}
17.백준(5585) 거스름돈
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int cnt = 0;
int Pay = 0;
cin >> Pay;
Pay = 1000 - Pay;
// 주어진 값에서 1000원을 뺀 값을 기준으로
if (Pay >= 500)
{
cnt++;
Pay = Pay - 500;
}
// 제일 높은 거스름돈부터 빼주면서 계산해준다.
if (Pay >= 100)
{
int temp = Pay / 100;
cnt = cnt + temp;
for (int i = 0; i < temp; i++)
Pay = Pay - 100;
}
if (Pay >= 50)
{
int temp = Pay / 50;
cnt = cnt + temp;
for (int i = 0; i < temp; i++)
Pay = Pay - 50;
}
if (Pay >= 10)
{
int temp = Pay / 10;
cnt = cnt + temp;
for (int i = 0; i < temp; i++)
Pay = Pay - 10;
}
if (Pay >= 5)
{
int temp = Pay / 5;
cnt = cnt + temp;
for (int i = 0; i < temp; i++)
Pay = Pay - 5;
}
if (Pay >= 1)
{
int temp = Pay / 1;
cnt = cnt + temp;
for (int i = 0; i < temp; i++)
Pay = Pay - 1;
}
cout << cnt << "\n";
return 0;
}
19.백준(5576) 콘테스트
#include <iostream>
#include <vector>
#include <algorithm>
#define SIZE 20
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// freopen("input.txt", "r", stdin);
vector<int>W(SIZE/2, 0);
vector<int>K(SIZE/2, 0);
for(int i=0; i<SIZE/2; i++)
cin >> W[i];
for(int i=0; i<SIZE/2; i++)
cin >> K[i];
sort(W.begin(), W.end());
sort(K.begin(), K.end());
int AnswerW = 0;
int AnswerK = 0;
AnswerW = W[9] + W[8] + W[7];
AnswerK = K[9] + K[8] + K[7];
cout << AnswerW << " " << AnswerK <<"\n";
return 0;
}
———————-
백준_브론즈_3
1. 백준(2577) 숫자의 개수
세 개의 자연수 A, B, C가 주어질 때 A × B × C를 계산한 결과에 0부터 9까지 각각의 숫자가 몇 번씩 쓰였는지를 구하는 프로그램을 작성하시오.
예를 들어 A = 150, B = 266, C = 427 이라면 A × B × C = 150 × 266 × 427 = 17037300 이 되고, 계산한 결과 17037300 에는 0이 3번, 1이 1번, 3이 2번, 7이 2번 쓰였다.
- 입력
첫째 줄에 A, 둘째 줄에 B, 셋째 줄에 C가 주어진다. A, B, C는 모두 100보다 크거나 같고, 1,000보다 작은 자연수이다.
- 출력
첫째 줄에는 A × B × C의 결과에 0 이 몇 번 쓰였는지 출력한다. 마찬가지로 둘째 줄부터 열 번째 줄까지 A × B × C의 결과에 1부터 9까지의 숫자가 각각 몇 번 쓰였는지 차례로 한 줄에 하나씩 출력한다.
#include <stdio.h>
#include <stdlib.h>
int main(){
int a, b, c;
int sum = 0;
int arr[10] = {0} ;
scanf("%d %d %d", &a, &b,&c);
sum = a * b * c;
int cnt = 0;
while(sum!=0){
cnt = sum %10;
switch (cnt)
{
case 0 :
arr[0] ++;
sum = sum /10;
break;
case 1 :
arr[1] ++;
sum = sum /10;
break;
case 2 :
arr[2] ++;
sum = sum /10;
break;
case 3 :
arr[3] ++;
sum = sum /10;
break;
case 4 :
arr[4] ++;
sum = sum /10;
break;
case 5 :
arr[5] ++;
sum = sum /10;
break;
case 6 :
arr[6] ++;
sum = sum /10;
break;
case 7 :
arr[7] ++;
sum = sum /10;
break;
case 8 :
arr[8] ++;
sum = sum /10;
break;
default:
arr[9] ++;
sum = sum /10;
break;
}
}
for(int i=0; i<10; i++){
printf("%d\n", arr[i]);
}
return 0;
}
2. 백준(2439) 별 찍기
첫째 줄에는 별 1개, 둘째 줄에는 별 2개, N번째 줄에는 별 N개를 찍는 문제 하지만, 오른쪽을 기준으로 정렬한 별(예제 참고)을 출력하시오.
-입력
첫째 줄에 N(1 ≤ N ≤ 100)이 주어진다.
-출력
첫째 줄부터 N번째 줄까지 차례대로 별을 출력한다.
#include <stdio.h>
#include <stdlib.h>
int main(void){
int N ;
scanf("%d", &N);
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(i+j >= N-1){ //인덱스를 이용하여 접근
printf("*");
}
else printf(" ");
}
printf("\n");
}
return 0;
}
3. 백준(2440) 별찍기 -3
첫째 줄에는 별 N개, 둘째 줄에는 별 N-1개, …, N번째 줄에는 별 1개를 찍는 문제
-입력
첫째 줄에 N(1 ≤ N ≤ 100)이 주어진다.
-출력
첫째 줄부터 N번째 줄까지 차례대로 별을 출력한다.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void){
int N = 0;
scanf("%d", &N);
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(i+j <N)
printf("*");
else
continue;
}
printf("\n");
}
return 0;
}
4. 백준(10872) 팩토리얼
0보다 크거나 같은 정수 N이 주어진다. 이때, N!을 출력하는 프로그램을 작성하시오.
-입력
첫째 줄에 정수 N(0 ≤ N ≤ 12)이 주어진다.
-출력
첫째 줄에 N!을 출력한다.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int Factorial(int n) {
if (n > 1)
return n * Factorial(n - 1);
else return 1;
}
int main(void){
int N;
scanf("%d", &N);
printf("%d\n",Factorial(N));
return 0;
}
5. 백준(10951) A+B - 4
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
-입력
입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 A와 B가 주어진다. (0 < A, B < 10)
-출력
각 테스트 케이스마다 A+B를 출력한다.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void){
int A,B;
while((scanf("%d %d", &A, &B)) ==2){
printf("%d\n", A+B);
}
return 0;
}
6. 백준(10817)세 수
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int>ans;
vector<int>::iterator it = ans.begin();
for(int i=0; i<3; i++){
int num = 0;
cin >> num;
ans.push_back(num);
}
sort(ans.rbegin(), ans.rend());
cout << ans[1];
return 0;
}
// 벡터를 이용하여 내림차순 정렬 이후 가운데 원소를 프린트하여 간단하게 해결가능
7. 백준(4153) 직각삼각형
#include <iostream>
#include <string>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
int main(){
while(true)
{
vector<int>ans(3,0);
for(int i=0; i<3; i++){
cin >> ans[i];
}
sort(ans.begin(), ans.end());
int a = ans[0];
int b = ans[1];
int c = ans[2];
if(a==0 && b==0 &&c==0){
break;
}
else
{
int sum = pow(a,2) + pow(b,2);
if(sum-(pow(c,2)) == 0){
cout <<"right"<<"\n";
}
else{
cout <<"wrong\n";
}
}
}
return 0;
}
8. 백준(1085) 직사각형에서 탈출
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
vector<int>temp(4,0);
int x,y,w,h;
cin >> x >> y >> w >> h;
int ans = 0;
temp[0] = w - x;
temp[1] = h - y;
temp[2] = x ;
temp[3] = y;
sort(temp.begin(), temp.end());
ans = temp[0];
cout << ans <<"\n";
return 0;
}
9. 백준(2747) 피보차니
#include <iostream>
#include <vector>
using namespace std;
vector<int>memory(1000001, 0);
int fib(int N){
if(N<=1)
return N;
else{
if(memory[N]==0){
memory[N] = fib(N-1) + fib(N-2);
return memory[N];
}//없는경우
else {
return memory[N];
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N = 0;
cin >> N;
cout << fib(N) << "\n";
return 0;
}
10. 백준(10250) ACM호텔
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int testCase = 0 ;
cin >> testCase;
while(testCase--){
int H,W,N;
int cnt = 0;
cin >> H >> W >> N;
// 호텔의 층 수 , 각 층의 방 수 , 몇 번째 손님
// 9 10 90
int q,r;//몫과 나머지를 저장
q = (N-1)/H;
r = (N-1)%H;
int answer = (r+1) *100 + q+1;
cout << answer <<"\n";
}// testCase
return 0;
}
———————-
백준_브론즈_4
1. 백준(1008) A/B
두 정수 A와 B를 입력받은 다음, A/B를 출력하는 프로그램을 작성하시오.
- 입력
첫째 줄에 A와 B가 주어진다. (0 < A, B < 10)
- 출력
첫째 줄에 A/B를 출력한다. 실제 정답과 출력값의 절대오차 또는 상대오차가 10-9 이하이면 정답
#include <stdio.h>
int main(){
double A,B;
long double C ;
scanf("%1lf %1lf", &A, &B);
C = A/ B;
printf("%.13Lf\n",C);
return 0;
}
2. 백준(10039) 평균 점수
상현이가 가르치는 아이폰 앱 개발 수업의 수강생은 원섭, 세희, 상근, 숭, 강수이다. 어제 이 수업의 기말고사가 있었고, 상현이는 지금 학생들의 기말고사 시험지를 채점하고 있다. 기말고사 점수가 40점 이상인 학생들은 그 점수 그대로 자신의 성적이 된다. 하지만, 40점 미만인 학생들은 보충학습을 듣는 조건을 수락하면 40점을 받게 된다. 보충학습은 거부할 수 없기 때문에, 40점 미만인 학생들은 항상 40점을 받게 된다. 학생 5명의 점수가 주어졌을 때, 평균 점수를 구하는 프로그램을 작성하시오.
-입력
입력은 총 5줄로 이루어져 있고, 원섭이의 점수, 세희의 점수, 상근이의 점수, 숭이의 점수, 강수의 점수가 순서대로 주어진다.
점수는 모두 0점 이상, 100점 이하인 5의 배수이다. 따라서, 평균 점수는 항상 정수이다.
- 출력
첫째 줄에 학생 5명의 평균 점수를 출력한다.
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[5] ={0}; // 학생 점수 저장 배열
int avg = 0 ; // 평균값 저장 변수
for(int i=0; i<5; i++)
scanf("%d", &arr[i]); //점수 입력 받기
for(int i=0;i<5;i++){
if(arr[i] >=40)
avg += arr[i];
else
avg += 40;
}//for 40점 이상은 그대로 미만은 40으로 고정
avg /= 5; // 점수총합/인원수
printf("%d ", avg);
printf("\n");
return 0;
}
3. 백준 (9498) 시험 성적
시험 점수를 입력받아 90 ~ 100점은 A, 80 ~ 89점은 B, 70 ~ 79점은 C, 60 ~ 69점은 D, 나머지 점수는 F를 출력하는 프로그램을 작성하시오.
-입력
첫째 줄에 시험 점수가 주어진다. 시험 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다.
-출력
시험 성적을 출력
#include <stdio.h>
int main(){
int A ;
scanf("%d", &A);
if (A>=90 && A <=100)
printf("A\n");
else if(A>=80 && A <90)
printf("B\n");
else if(A>=70 && A <80)
printf("C\n");
else if(A>=60 && A< 70)
printf("D\n");
else
printf("F\n");
return 0;
}
4. 백준(2753) 윤년
연도가 주어졌을 때, 윤년이면 1, 아니면 0을 출력하는 프로그램을 작성하시오. 윤년은 연도가 4의 배수이면서, 100의 배수가 아닐 때 또는 400의 배수일 때이다.예를 들어, 2012년은 4의 배수이면서 100의 배수가 아니라서 윤년이다. 1900년은 100의 배수이고 400의 배수는 아니기 때문에 윤년이 아니다. 하지만, 2000년은 400의 배수이기 때문에 윤년이다.
-입력
첫째 줄에 연도가 주어진다. 연도는 1보다 크거나 같고, 4000보다 작거나 같은 자연수이다.
-출력
첫째 줄에 윤년이면 1, 아니면 0을 출력한다.
#include <stdio.h>
#include <stdlib.h>
int main(){
int n ;
scanf("%d", &n);
if(n%4==0 && (n%100!=0 || n%400 ==0)){
printf("%d\n",1);
}
else printf("%d\n",0);
return 0;
}
5. 백준(5543) 상근날드
상근날드에서 가장 잘 팔리는 메뉴는 세트 메뉴이다. 주문할 때, 자신이 원하는 햄버거와 음료를 하나씩 골라, 세트로 구매하면, 가격의 합계에서 50원을 뺀 가격이 세트 메뉴의 가격이 된다.
햄버거는 총 3종류 상덕버거, 중덕버거, 하덕버거가 있고, 음료는 콜라와 사이다 두 종류가 있다.
햄버거와 음료의 가격이 주어졌을 때, 가장 싼 세트 메뉴의 가격을 출력하는 프로그램을 작성하시오.
-입력
입력은 총 다섯 줄이다. 첫째 줄에는 상덕버거, 둘째 줄에는 중덕버거, 셋째 줄에는 하덕버거의 가격이 주어진다. 넷째 줄에는 콜라의 가격, 다섯째 줄에는 사이다의 가격이 주어진다. 모든 가격은 100원 이상, 2000원 이하이다.
-출력
첫째 줄에 가장 싼 세트 메뉴의 가격을 출력한다
#include <stdio.h>
#include <stdlib.h>
# define N 5
int main(){
int arr[N] = {0};
for(int i=0; i< N; i++){
scanf("%d", &arr[i]);
}
int min_h = arr[0];
int min_s = arr[3];
for(int i=1; i<N; i++){
if(i<3){
if(min_h >=arr[i]){
min_h = arr[i];
}
}
else{
if(min_s >=arr[i]){
min_s = arr[i]; }
}
}
int sum = (min_h + min_s) -50;
printf("%d\n", sum);
return 0;
}
6. 백준(2752) 세수정렬
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int>ans;
vector<int>::iterator it = ans.begin();
for(int i=0; i<3; i++){
int num = 0;
cin >> num;
ans.push_back(num);
}
sort(ans.begin(), ans.end());
for(it = ans.begin(); it!=ans.end(); it++){
cout <<*it << " "; }
return 0;
}
7.백준(2480) 주사위 세개
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
vector<int>ans;
vector<int>::iterator it = ans.begin();
int A,B,C;
int sum = 0;
cin >> A >> B >> C;
ans.push_back(A);
ans.push_back(B);
ans.push_back(C);
sort(ans.begin(), ans.end());
if (A == B && A== C){
sum = 10000 + (A*1000);
cout << sum;
return 0;
}
else if(A==B || A==C){
sum = 1000+(A*100);
cout << sum;
return 0;
}
else if(C==B){
sum = 1000+(C*100);
cout <<sum;
return 0;
}
else{
cout <<ans[2]*100;
}
return 0;
}
8. 백준(10797) 10부제
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int check = 0;
int cnt = 0;
cin >>check;
for(int i =0; i<5; i++){
int temp ;
cin >>temp;
if(temp == check)
cnt ++;
}
cout << cnt;
return 0;
}
9. 백준(2525) 오븐시계
KOI 전자에서는 건강에 좋고 맛있는 훈제오리구이 요리를 간편하게 만드는 인공지능 오븐을 개발하려고 한다. 인공지능 오븐을 사용하는 방법은 적당한 양의 오리 훈제 재료를 인공지능 오븐에 넣으면 된다. 그러면 인공지능 오븐은 오븐구이가 끝나는 시간을 분 단위로 자동적으로 계산한다. 또한, KOI 전자의 인공지능 오븐 앞면에는 사용자에게 훈제오리구이 요리가 끝나는 시각을 알려 주는 디지털 시계가 있다. 훈제오리구이를 시작하는 시각과 오븐구이를 하는 데 필요한 시간이 분단위로 주어졌을 때, 오븐구이가 끝나는 시각을 계산하는 프로그램을 작성하시오
입력
첫째 줄에는 현재 시각이 나온다. 현재 시각은 시 A (0 ≤ A ≤ 23) 와 분 B (0 ≤ B ≤ 59)가 정수로 빈칸을 사이에 두고 순서대로 주어진다. 두 번째 줄에는 요리하는 데 필요한 시간 C (0 ≤ C ≤ 1,000)가 분 단위로 주어진다.
출력
첫째 줄에 종료되는 시각의 시와 분을 공백을 사이에 두고 출력한다. (단, 시는 0부터 23까지의 정수, 분은 0부터 59까지의 정수이다. 디지털 시계는 23시 59분에서 1분이 지나면 0시 0분이 된다.)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int H ,M ,T;
cin >> H >> M >> T;
M += T;
while(M>=60){
H = H + M/60;
M = M%60;
}
while(H>=24){
H= H - 24;
}
cout << H << " " << M;
return 0;
}
———————-
백준_브론즈_5
1. 백준(1000번) A+B
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성.
- 입력 : 첫째 줄에 A와 B가 주어진다.
(0 < A, B < 10) - 출력 : 첫째 줄에 A+B를 출력한다.
#include <stdio.h>
int void(){
int A,B;
//두 개의 정수를 받을 A,B선언
scanf("%d %d", &A, &B);
//A,B입력
int C = A + B;
//A+B 데이터를 받을 새로운 C변수 선언
printf("%d\n", C); //출력
return 0;
}
2. 백준(1001) A-B
두 정수 A와 B를 입력받은 다음, A-B를 출력하는 프로그램을 작성
- 첫째 줄에 A와 B가 주어진다. (0 < A, B < 10)
- 첫째 줄에 A-B를 출력한다.
#include <stdio.h>
int main(void){
int A,B;
//두 개의 정수를 받을 A,B선언
scanf("%d %d", &A, &B);
//A,B입력
int C = A - B;
//A-B 데이터를 받을 새로운 C변수 선언
printf("%d\n", C);
return 0;
}
3. 백준(2557) Hello World
- 입력 :없음
- 출력 : Hello World!를 출력
#include <stdio.h>
int main(void){
printf("Hello World!\n");
return 0;
}
4. 백준(8393) 합
n이 주어졌을 때, 1부터 n까지 합을 구하는 프로그램을 작성
- 입력: n (1 ≤ n ≤ 10,000)
- 출력: 1부터 n까지 합을 출력
#include <stdio.h>
int main(void){
int n ;
scanf("%d", &n);
int Sum = 0; // 1부터 n까지의 합을 저장할 Sum변수 선언
for(int i=0; i<=n; i++){
Sum = Sum+i;
//for문을 돌면서 1부터 n까지의 합을 Sum의 저장
}
printf("%d\n",Sum);
return 0;
}
5. 백준(1550) 16진수
16진수 수를 입력받아서 10진수로 출력하는 프로그램을 작성
-
입력 : 첫째 줄에 16진수 수가 주어진다. 이 수의 최대 길이는 6글자이다. 16진수 수는 0~9와 A~F로 이루어져 있고, A~F는 10~15를 뜻한다. 또, 이 수는 음이 아닌 정수
-
출력 : 첫째 줄에 입력으로 주어진 16진수 수를 10진수로 변환해 출력
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
int answer = 0;
char *ch = malloc(6);
scanf("%s", ch);
if(*ch == 'A'){
answer = 10;
}
else if(*ch == 'B'){
answer = 11;
}
else if(*ch == 'C'){
answer = 12;
}
else if (*ch == 'D'){
answer = 13;
}
else if (*ch == 'E'){
answer = 14;
}
else if (*ch == 'F'){
answer = 15;
}
else {
answer = atoi(ch);
}
printf("%d\n", answer);
return 0;
}
6.백준(5338) 마이크로소프트 로고
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
cout << " _.-;;-._" <<endl;
cout << "'-..-'| || | "<<endl;
cout << "'-..-'|_.-;;-._|" <<endl;
cout << "'-..-'| || |" <<endl;
cout << "'-..-'|_.-''-._|"<<endl;
return 0;
}
———————-
———————-BOJ—————–
Programmers
Greedy
Level_1.체육복
체육복
그리디 알고리즘을 이용하야 단순하게 앞뒤 체육복을 빌려줄 수 있는지 확인만 하면 되는 문제이다
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int solution(int n, vector<int> lost, vector<int> reserve) {
int answer = 0;
vector<int>Student(n, 1);
int move[2] = {-1,1};
sort(lost.begin(), lost.end());
sort(reserve.begin(), reserve.end());
for(int i=0; i<reserve.size(); i++)
Student[reserve[i]-1] ++;
for(int i=0; i<lost.size(); i++)
Student[lost[i]-1] --;
for(int i=0; i<n; i++){
if(Student[i] == 2) //체육복의 여벌이 존재하는경우 앞뒤 확인
for(int j=0; j<2; j++){ //앞뒤 홧인
int temp = i+move[j]; //앞,뒤 이동
if(temp >=0 && temp <n){ //인덱스 범위내
if(Student[temp] == 0 && Student[i] ==2){ //체육복이 필요하다면
//양 옆을 빌려줄때를 대비해서
Student[i] --; //내꺼 하나빼고 친구 하나 주기
Student[temp]++;
} //체육복 필요 _if
} //범위_if
} //앞뒤확인_For
} //전체 학생확인_For
for(int i=0; i<n; i++){
if(Student[i] !=0){
answer ++;
}
}
return answer;
}
———————-Greedy
Stack/Queue
Level_1. 같은 숫자는 싫어
스택을 이용하여 구현 기본적인 스택문제
#include <vector>
#include <algorithm>
#include <iostream>
#include <stack>
using namespace std;
vector<int> solution(vector<int> arr)
{
stack<int>S;
S.push(arr[0]);
for(auto it = arr.begin()+1; it!= arr.end(); it++){
if(S.top() != *it){S.push(*it);}
}
vector<int> answer(S.size(),0);
for(int i=S.size()-1; i>=0; i--){
answer[i] = S.top();
S.pop();
}
return answer;
}
Level_2.기능개발
큐를 이용하여 구현하는 문제이며 끝나는 시간을 큐의 넣고 비교해가면서 풀면 쉽게 풀 수 있다.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
vector<int> solution(vector<int> progresses, vector<int> speeds) {
vector<int> answer;
int N = progresses.size();
queue<int>develope;
for(int i=0; i<N; i++){
int temp = progresses[i];
int cnt = 0;
while(temp<100){
temp += speeds[i];
cnt++;
}
develope.push(cnt);
} //각 작업당 필요한 시간을 계산하여 큐의 삽입
int temp = 0;
while(!develope.empty()){ //큐의 원소가 있다면
int answer_cnt = 1;
temp = develope.front(); //큐의 제일 앞에 원소를 가져옴
develope.pop(); // 제거
while(temp >= develope.front() && !develope.empty()){
// 큐의 원소가 있고 나중 작업이 이미 끝나있다면
answer_cnt++; //카운터 증가
develope.pop(); //삭제
} //while
answer.push_back(answer_cnt);
// 카운터 저장
}//for
return answer;
}
Level_2. 프린터
- 프린터 (Level_2)
큐를 이용하여 구현하는 문제이며 구조체를 이용하여 비교해야하는 문제이고 기본문제보다는 약간의 응용이 필요한 문제이다.
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct Document{
int Important;
int Index;
}Document;
// 문서정보를 구조체 선언
int solution(vector<int> priorities, int location) {
int answer = 1;
Document D;
queue<Document>Q;
for(int i=0; i<priorities.size(); i++){
D.Index = i+1;
D.Important = priorities[i];
Q.push(D);
}
// 주어진 조건에 맞게 큐에 삽입
sort(priorities.rbegin(), priorities.rend());
// 내림차순으로 정렬
int idx = 0;
while(!Q.empty()){
int temp = Q.front().Important;
// 큐에 저장된 가장 맨 앞에 있는원소를 가져옴
if(temp == priorities[idx]){
// 그 값과 원소중 가장 큰값이 같다면 숫자 1증가 ,가장 큰 원소 삭제, 큐 원소 제거
if(Q.front().Index -1 == location){
// 그 값이 원하는 타겟 넘버라면 리턴
return answer;
}
idx++;
answer++;
Q.pop();
}
else{
// 그게 아니라면 큐에 제일 앞에 있던 원소를 뒤로 보내기
D.Index = Q.front().Index;
D.Important = temp;
Q.pop();
Q.push(D);
}
}
}
Level_2.올바른 괄호
스택을 이용하여 구현하는 문제이며 스택의 기본문제라고 볼 수 있다. 어렵지 않게 해결 가능하다.
#include <string>
#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
bool solution(string s)
{
bool answer = true;
int len = s.length();
stack<char>S;
for(int i=0; i<len; i++){
if(s[i] =='(')
S.push(s[i]);
else if(s[i] == ')'){
if(S.empty()){answer = false; return answer;}
S.pop();
}
}//for
if(!S.empty())
answer = false;
return answer;
}
Level_2.주식가격
스택과 큐를 이용하여 구현하는 문제인데 사용하지않고도 해결가능 어려운 문제는 아닌듯하다.
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
vector<int> solution(vector<int> prices) {
vector<int> answer;
bool check = false;
// 주식 가격이 끝까지 가는지 확인하기 위한 변수
for(int i=0; i<prices.size(); i++){
check = false;
int cnt = 1;
// 초기 값은 1
int temp = prices[i];
// 비교 값 셋팅
for(int j=i+1; j<prices.size(); j++){
if(temp<=prices[j]){
check = true;
cnt ++;
} // 반복을 돌면서 만약에 다음날까지 주식가격이 떨어지지않았으면 갯수 1개 증가
else{
// 다음날 주식가격이 떨어졌으면 체크를 false로 바꾸고 여태까지 지나온 일수를 answer에 푸쉬하고 브레이크
check = false;
answer.push_back(cnt);
break;
}
}
if(check == true){
// 주식가격이 끝가지 간경우 총 요일- 현재 요일로 계산
answer.push_back(prices.size()-(i+1));
}
}
// 맨 마지막은 무조건 0이므로
answer.push_back(0);
return answer;
}
Level_2. 다리를 지나는 트럭
큐를 이용하는 문제처럼 보이는데 구현이 쉽지않다 실패원인을 찾아야함
실패코드
//실패 코드 ... 뭐가 잘못된걸까
#include <string>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
int solution(int bridge_length, int weight, vector<int> truck_weights) {
int answer = 1;
int len = bridge_length;
for(int i=0; i<truck_weights.size()-1; i++){
int temp = truck_weights[i] + truck_weights[i+1];
if(temp <= weight){
answer ++;
}
else{
answer = answer + len;
}
}
answer = answer + len;
return answer;
}
성공
트럭이 전진함에 있어서 만약 다음 트럭이 지나갈 수 없다면 큐에 0을 채워넣는 방법으로 문제를 간단하게 해결할 수 있었다.
#include <string>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
int solution(int bridge_length, int weight, vector<int> truck_weights) {
queue<int>wait;
queue<int>passing;
int len = bridge_length;
for(int i=0; i<len; i++)
passing.push(0);
// 주어진 다리 길이에 맞게 최초 0을 삽입한 큐 생성
for(auto t : truck_weights)
wait.push(t);
// 트럭 정보 입력
int answer = 0;
int W = 0;
int temp = 0;
// 정답과 현재 다리의 총 무게, 건너야하는 트럭 정보 변수 선언
while(!wait.empty()){ //대기 트럭이 있는동안 반복
answer ++;
// 1초가 지나고
temp = wait.front(); //대기 트럭 정보 저장
W = W-passing.front(); // 다리를 건넌 트럭은 무게에서 제외
passing.pop(); // 다리에 제일 선두에 있는 트럭 제거
if( W + temp <= weight){ // 현재 다리 총 무게 + 대기 트럭이 건널 수 있으면
W = W+temp; wait.pop(); // 대기 트럭 다리에 올리고
passing.push(temp); //한 칸 전진
}
else{
passing.push(0); // 만약 대기 트럭을 못 올린다면 0으로 채움
}
} //while
answer = answer + bridge_length; //마지막 트럭만 보내면 끝임
return answer;
}
———————-Stack/Queue
Heap
Level_2.더 맵게
우선순위 큐를 이용하여 구현하는 문제이며 주어진 조건에 맞게 구현하면 쉽게 해결이 가능한 문제였다.
- 주어진 스코빌 지수에 맞게 오름차순으로 우선순위 큐 생성
- 큐의 원소가 있다면
- 만약 큐의 첫 번째 원소가 조건에 만족한다면 나머지도 다 만족하므로 종료
- 첫 번째 원소가 조건에 만족하지 않고 더 이상 큐의 원소가 없다면 답이 없음
- 그게 아니라면 주어진 연산에 맞게 연산 후 다시 우선순위 큐에 삽입
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
int mixed_scoville(int a, int b);
int solution(vector<int> scoville, int K) {
int answer = 0;
int len = scoville.size();
bool check = false;
priority_queue<int, vector<int> , greater<int>>pq; //오름차순
for(int i=0; i<len; i++)
pq.push(scoville[i]);
while(!pq.empty()){ //pq의 원소가 있다면
if(pq.top()>=K){break;} // 오름차순 정렬이므로 제일 처음 숫자가 K이상이면 된다.
int a = pq.top();
pq.pop();
if(pq.empty()){check = true; break;} // 하나만 남았는데 위 조건에서 빠지지 못했다면 답이 없음
int b = pq.top();
pq.pop();
int c = mixed_scoville(a,b); // 조건에 맞게 연산
pq.push(c); // 연산한 값을 다시 Push
answer ++; // 연산의 횟수 추가
}
if(check == true){
return -1;
}
return answer;
}
int mixed_scoville(int a, int b){
int temp = a + (b*2);
return temp ;
}
———————-Heap
Sort
Level_1. K번째수
문제에서 주어진 조건에 맞게 벡터를 복사 후 정렬하며 쉽게 해결이 가능한 문제이다.
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
vector<int> solution(vector<int> array, vector<vector<int>> commands) {
vector<int> answer;
int from,to = 0;
int target = 0;
for(int i=0; i< commands.size(); i++){
vector<int>temp ;
from = commands[i][0]-1;
to = commands[i][1];
target = commands[i][2]-1;
// from , to , target 확인
for(int k = from; k<to; k++)
temp.push_back(array[k]);
// 반복문을 이용하여 from ~ to 벡터 복사
sort(temp.begin(), temp.end());
// 정렬
answer.push_back(temp[target]);
// 원하는 인덱스 값 정답 벡터에 push
}
return answer;
}
Level_2 가장 큰 수
테스트 케이스는 모두 통과하였지만 채점 결과는 참담하다… 어떤식으로 해결해야할지…
실패 코드
//실패 코드
#include <string>
#include <vector>
#include <iostream>
using namespace std;
string solution(vector<int> numbers) {
int size = numbers.size();
string answer = "";
int max = 0;
int index = 0;
vector<string>str;
for(auto n : numbers){
str.push_back(to_string(n));
}
for(int i=0; i<size-1; i++){
max = str[i][0]; //제일 앞에 있는 원소
for(int j=i+1; j<size; j++){
int idx = 1;
if(max<str[j][0]){
max = str[j][0];
index = j;
}
else if(max ==str[j][0]){
while(str[i][idx]!=NULL && str[j][idx]!=NULL){
if(str[i][idx] == str[j][idx])
idx++;
else{
index = str[i][idx] > str[j][idx]?i:j;
break;
}
}
if(str[i][idx] == NULL){
char temp = str[i][idx-1];
while(1){
if(temp == str[j][idx]){
idx++;
}
else break;
}
index = temp>str[j][idx]?i:j;
}else if (str[j][idx] == NULL){
char temp = str[j][idx-1];
while(1){
if(temp == str[i][idx]){
idx++;
}
else break;
}
index = str[i][idx]>str[j][idx-1]?i:j;
}
} // 같은값이 나온 경우
}
answer = answer + str[index];
swap(str[i], str[index]);
}
answer =answer + str[size-1];
if(answer[0]=='0'){
answer = "0";
}
// for(auto s: str){
// cout << s << " ";
// }
return answer;
}
성공
- 단순하게 string 값을 더하는 조건식을 세우면 되는거였는데 너무 복잡하게 생각하려고 했다…. ex) [30, 3] -> a+b = 303 , b+a = 330 으로 쉽게 식을 세울 수 있었음..
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool com(string a, string b){
return a+b > b+a;
}
string solution(vector<int> numbers) {
string answer = "";
vector<string>Answer;
for(auto number : numbers)
Answer.push_back(to_string(number));
sort(Answer.begin(), Answer.end(), com);
for(auto A : Answer)
answer = answer + A;
if(answer[0] == '0') {return "0";}
return answer;
}
Level_2. H-index
알고리즘만 잘 구현한다면 어렵지 않게 해결이 가능하다 단, 조건에서 주어진 h가 배열안에 있는 숫자가 아니고 1개씩 커지는 숫자다..함정 조심
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int solution(vector<int> citations) {
sort(citations.begin(), citations.end());
vector<int>Answer;
int answer = 0;
int size = citations.size();
int max = citations[size-1];
int idx = 0;
for(int i =1; i<=max; i++){
// 하나씩 증가하는 i
for(int j=idx; j<size; j++){
if(i <= citations[j]){
idx = j;
break;
// 인용횟수가 조건 이상이라면 인덱스를 기억하고 멈춤
}
}
int Up = size-idx;
int Dw = size - Up +1;
// 인용횟수 나머지 계산
if(Up>=i && Dw<=i){
Answer.push_back(i);
// 주어진 조건에 맞다면 정답 벡터에 푸쉬
}
}
if(Answer.size()==0){return 0;} //예외조건
sort(Answer.rbegin(), Answer.rend());
answer = Answer[0];
// 내림차순으로 정렬 후 최대값 저장
return answer;
}
———————-Sort
Hash
Level.2 전화번호 목록
- 전화번호 목록 (Level_2)
해쉬 테이블을 이용하여 구현하는 문제이다. 쉽게 생각할 수 있는 방법으로 구현한다면 테스트케이스는 맞더라도 효율성 문제에 걸린다. 해쉬 테이블에 대한 기본적인 이해가 필요하다.
실패코드
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
bool com(string a, string b){
return a.length()<b.length();
}
bool solution(vector<string> phone_book) {
bool answer = true;
sort(phone_book.begin(), phone_book.end(), com);
string temp;
for(int i=0; i<phone_book.size(); i++){
temp = phone_book[i];
bool check = false;
int len = temp.length();
for(int j= i+1; j<phone_book.size(); j++){
for(int k=0; k<len; k++){
if(temp[k] == phone_book[j][k])
check = true;
else{
check = false;
break;
}
}
if(check == true){
return false;
}
}
}
answer = true ;
return answer;
}
성공
최초 최소길이를 계산 후 최소길이만큼만 비교해주는 방식으로 해결했다. 이 때 주의할 점은 최소길이는 같지만 접두어가 다른경우가 발생할 수 있어서 한 번 더 확인하는 과정이 필요하다.
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <map>
using namespace std;
bool com(string a, string b){
return a.length()<b.length();
}
bool solution(vector<string> phone_book) {
bool answer = true;
sort(phone_book.begin(), phone_book.end(), com);
map<string, int>M;
int size = phone_book[0].length(); //최소 길이 저장
int idx =0;
bool check = true;
while(phone_book[idx].length() <= size && idx<phone_book.size())
{ M.insert(make_pair(phone_book[idx], idx));
idx++;
}
// 최소 길이 만큼 MAP에 인덱스와 함께 저장
// ex) ["119", "114", "112", "123223123", "1231231234"]
// -> {"112",0 }, {"114", 1}, {"119", 2}
for(int i= idx; i<phone_book.size(); i++){ // 최소길이를 저장한 다음 인덱스부터 확인
string str = "";
for(int j=0; j<size; j++)
str += phone_book[i][j];
// 최소 길이 부분만큼만 뽑음
if(M.count(str) == 0) // 1번도 들어온적이 없다면 새롭게 인덱스와 함께 추가
M.insert(make_pair(str, i));
else{ //이미 똑같은 값이 있는경우 다시 확인해봐야함
int tmp = M[str];
int tmp_sz = phone_book[tmp].length();
// 저장했던 인덱스를 이용하여 탐색 시작
// 현재 값과 그전에 저장되어있던 값들을 하나씩 비교해보고 서로 다르다면 멈춤
for(int k=size; k<tmp_sz; k++){
if(phone_book[tmp][k] != phone_book[i][k]){
check = false;
break;
} // 접두사가 아닌경우
else check = true; //접두사인 경우
}
if(check == false)//만약 접두사가 아니라면 그냥 진행
answer = true;
else //접두사라면 종료
return false;
}
}
return answer;
}
Level_2. 위장
해쉬 테이블을 이용하여 구현하는 문제이다. 수학적 수식을 생각하는게 조금은 어려웠던 문제이지만 패턴을 찾는다면 쉽게 해결 가능하다.
#include <string>
#include <vector>
#include <map>
#include <iostream>
using namespace std;
int solution(vector<vector<string>> clothes) {
int answer = 1;
map<string, int>M;
for(int i=0; i<clothes.size(); i++){
if(M.count(clothes[i][1]) == 0)
M.insert(make_pair(clothes[i][1], 1) );
else
M[clothes[i][1]] ++;
}
// 종류별로 갯수를 확인함
for(auto m : M){
answer = answer * (m.second+1);
} //자기 자신도 포함이므로 +1
answer = answer -1; //아무런 옷도 입지않은 상태는 빼준다.
return answer;
}