[알고리즘] 문제풀이 연습

[0705 복습] 백준2164 + 연습문제 5개

ddgoori 2019. 7. 5. 23:34

백준2164 

 

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

 

2164번: 카드2

N장의 카드가 있다. 각각의 카드는 차례로 1부터 N까지의 번호가 붙어 있으며, 1번 카드가 제일 위에, N번 카드가 제일 아래인 상태로 순서대로 카드가 놓여 있다. 이제 다음과 같은 동작을 카드가 한 장 남을 때까지 반복하게 된다. 우선, 제일 위에 있는 카드를 바닥에 버린다. 그 다음, 제일 위에 있는 카드를 제일 아래에 있는 카드 밑으로 옮긴다. 예를 들어 N=4인 경우를 생각해 보자. 카드는 제일 위에서부터 1234 의 순서로 놓여있다. 1을 버리

www.acmicpc.net

c++ deque를 이용하면 쉽게 풀 수 있다.

// BJ 2164
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <deque>
using namespace std;

int main(void) {

	int N;
	cin >> N;

	deque<int> dp;

	for (int i = 1; i <= N; i++) {
		dp.push_back(i);
	}

	

	while (dp.size() != 1) {
	
		dp.pop_front();
		dp.push_back(dp.front());
		dp.pop_front();
	
	}

	printf("%d", dp.front());
	return 0;




}

부연 설명!

 

처음 풀 때, (2)과정에서 앞에 것을 뒤로 복사하는 과정만 있는 것을,

앞에 것을 뒤로 아예 옮겨버린다고 착각했었다.(컴퓨팅적 사고부족)

(2)로 맨 앞 것을 뒤로 복사했으면, (3)을 통해 맨 앞 것을 지워줘야 한다. 

그렇게 함으로써 비로소 문제의 말처럼 "맨 앞에 것을 뒤로 옮긴 것"으로 된다.

(3)의 과정이 빠지면 "맨 앞에 것을 뒤로 복사한 것 (맨 앞에도 그래도 남긴 채)"밖에 안된다.

 

다행히 스터디장님이 잘 설명해주셔서 바로 이해할 수 있었다!!

(1) dp.pop_front();

(2) dp.push_back(dp.front());

(3) dp.pop_front();

여기서 (1), (2), (3)을 쪼개서 생각해보면

(1) dp.pop_front(); 카드 더미의 맨 앞 카드 버린다.

(2) dp.push_back(dp.front()); 맨앞 카드를 복사해서 맨 뒤에 넣는다.

(3) dp.pop_front(); 맨 앞 카드를 지운다.

 

 

https://hyeonstorage.tistory.com/325

 

[STL] deque 정리 및 예제

[STL] deque 정리 및 예제 deque 컨테이너는 vector 컨테이너와 기능과 동작이 비슷한 컨테이너로 vector의 단점을 보완하는 몇가지 특징을 갖는다. deque도 vector 컨테이너와 같이 시퀀스 컨테이너이며 배열 기..

hyeonstorage.tistory.com

summary

 

[STL] deque

 

#include <deque>

//선언 : 
deque<int> dq;

//dq의 앞쪽에 x를 추가
dq.push_front(x);

//dq의 끝 쪽에 x를 추가
dq.push_back(x);

//dq의 앞쪽 첫 원소 삭제
dq.pop_front();

//dq의 끝 원소 삭제
dq.pop_back();

//dq의 첫 번째 원소를 참조
dq.front();

//dq의 마지막 원소를 참조
dq.back();

//dq가 비었는지 조사
dq.empty();

//dq의 모든 원소 제거
dq.clear();

//dq의 원소 개수
dq.size();


 


알골 연습문제 90제 : 1~5번

 

1. 1부터 N까지 M의 배수합 
자연수 N이 입력되면 1부터 N까지의 수 중 M의 배수합을 출력하는 프로그램을 작성하세요.
▣ 입력설명 첫 줄에 자연수 N과 M이 차례대로 입력됩니다.(3<=M<N<=1000)
▣ 출력설명 첫 줄에 M의 배수합을 출력한다

 

// 1번 문제 : 1부터 N까지 M의 배수합

#include <iostream>
using namespace std;

int caculation(int a, int b) {
	
	int sum = 0;
	for (int i = 1; i <= a; i++) {
		if (i % b == 0) sum += i;
	}
	return sum;
}

int main() {

	int N, M;
	cin >> N >> M;

	cout << caculation(N, M);
}

 

2. 자연수의 합 
자연수 A, B가 주어지면 A부터 B까지의 합을 수식과 함께 출력하세요.
▣ 입력설명 첫 줄에 자연수 A, B가 공백을 사이에 두고 차례대로 입력된다. (1<=A<B<=100)
▣ 출력설명 첫 줄에 더하는 수식과 함께 합을 출력합니다.

// 2번 문제 - 자연수 A, B가 주어지면 A부터 B까지의 합을 수식과 함께 출력하세요.

#include <iostream>
using namespace std;

int main() {

	int A, B, sum = 0;
	cin >> A >> B;

	for (int i = A; i <= B; i++) {
		sum += i;
	}

	for (int i = A; i <= B; i++) {
	
		if (i == B) {
			cout << i;
		}
		else 
		{
			cout << i << " + ";
		}
	}
	
	cout <<" = "<< sum;
}

 

다른 풀이

#include<stdio.h>

int main(){
	int a, b, sum=0, i;
    
	scanf("%d %d", &a, &b);
    
	for(i=a; i<b; i++){
		sum+=i;
		printf("%d + ", i);
	}
    
	printf("%d = %d\n", i, sum+i);
    
	return 0;
}

 

 

3. 진약수의 합 
자연수 N이 주어지면 자연수 N의 진약수의 합을 수식과 함께 출력하는 프로그램을 작성하세 요.
▣ 입력설명 첫 줄에 자연수 N이 주어집니다. (3<N<=100)
▣ 출력설명 첫 줄에 더하는 수식과 함께 합을 출력합니다.

 

//문제 3번 - 자연수 N이 주어지면 자연수 N의 진약수의 합을 수식과 함께 출력하는 프로그램을 작성하세 요.
// 6의 약수 : 1 2 3 6
// 6의 진약수 : 1 2 3

#include <iostream>
using namespace std;

int main() {

	int N;
	int sum = 1;
	cin >> N;

	cout << "1";

	for (int i = 2; i <N; i++) {
		if (N%i == 0) {
			sum += i;
			cout << " + " << i;
		}
	}
	cout << " = " << sum;
}

 

 

4. 나이 차이
N(2<=N<=100)명의 나이가 입력됩니다. 이 N명의 사람 중 가장 나이차이가 많이 나는 경우는 몇 살일까요? 최대 나이 차이를 출력하는 프로그램을 작성하세요.
▣ 입력설명 입력파일은 input.txt로 한다. 첫 줄에 자연수 N(2<=N<=100)이 입력되고, 그 다음 줄에 N개의 나이가 입력된다.
▣ 출력설명 출력파일은 output.txt로 한다. 첫 줄에 최대 나이차이를 출력합니다.

// 4번 문제 - N(2<=N<=100)명의 나이가 입력됩니다. 이 N명의 사람 중 가장 나이차이가 많이 나는 경우는 몇 살일까요? 최대 나이 차이를 출력하는 프로그램을 작성하세요.

#include <iostream>
#include <fstream>
using namespace std;

int main() {

	int N, temp;
	int arr[100];

	ifstream is;
	is.open("input.txt");

	is >> N;
	for (int i = 0; i < N; i++) {
		is >> arr[i];
	}

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (arr[j] > arr[j+1]) {
				temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
		}
	}

	ofstream out;
	out.open("../output.txt");
	out << arr[N - 1] - arr[0];

	//for (int i = 0; i < N; i++) {
	//	cout << arr[i] << " ";
	//}


}

 

다른 풀이

#include<iostream>
using namespace std;
int main(){
	//freopen("input.txt", "rt", stdin);
	int n, i, a, max=-2147000000, min=2147000000;
	
    cin>>n;
    
	for(i=1; i<=n; i++){
		cin>>a;
		if(a>max) max=a;
		if(a<min) min=a;
	}
    
	cout<<max-min;
    
	return 0;
}

 

 

5. 나이계산 
주민등록증의 번호가 주어지면 주민등록증 주인의 나이와 성별을 판단하여 출력하는 프로그램 을 작성하세요. 주민등록증의 번호는 -를 기준으로 앞자리와 뒷자리로 구분된다. 뒷자리의 첫 번째 수가 1이면 1900년대생 남자이고, 2이면 1900년대생 여자, 3이면 2000년대 생 남자, 4이면 2000년대생 여자이다. 올해는 2019년입니다. 해당 주민등록증 주인의 나이와 성별을 출력하세요.
▣ 입력설명 첫 줄에 주민등록증 번호가 입력됩니다.
▣ 출력설명 첫 줄에 나이와 성별을 공백을 구분으로 출력하세요.  성별은 남자는 M(man), 여자는 W(Woman)로 출력한다.

 

// 복습! 5번 문제 - 나이계산 2 (문자열 컨트롤)
// 아스키 'A' ~ 'Z' 65~90
// 아스키 'a' ~ 'z' 97~122
// 아스키 '0' ~ '9' 48~57
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {

	//freopen("input.txt", "rt", stdin); //읽어와서 stdin으로 넘겨
	char ipin[20];
	int year, age;

	scanf("%s", &ipin);
	//연도
	if (ipin[7] == '1' || ipin[7] == '2')
		year = 1900 + ((ipin[0] - 48) * 10 + (ipin[1] - 48)); //a[0]은 문자 7임 ascii -  48해야 진짜 숫자가 나옴
	else
		year = 2000 + ((ipin[0] - 48) * 10 + (ipin[1] - 48));
	//연도를 알면 2019 기준 나이 알 수 있음
	age = 2019 - year + 1;
	printf("%d ", age);

	if (ipin[7] == '1' || ipin[7] == '3')
		printf("M");
	else
		printf("W");

	return 0;
}