728x90
반응형

min (max) 함수

파이썬에서는 여러 대상들(리스트 등) 중 가장 큰 값 또는 가장 작은 값을 구하는 함수가 있다.
min, max 함수인데, 아래 방법을 사용하면 이런 함수들을 좀 더 잘(?) 활용할 수 있다.

함수 Parameter에 key=func 주기

list_num = [1, 2, 5, 4, 5, 5, 6, 7, 8, 1]

print(max(list_num, key=list_num.count))

# count가 가장 많은 5가 출력


위 코드는 list_num.count를 list_num을 대상으로 실행하고, 해당 값들의 최대값을 출력한다.
따라서 list_num 내부에 가장 개수가 많은 5가 출력된다.


728x90
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[Python] Yahoo_fin 모듈  (0) 2022.09.11
[Python] Paramiko 모듈  (0) 2022.07.07
[Python] 데코레이터 (@, Decorator)  (0) 2022.03.21
[python] lambda 표현식  (0) 2022.01.07
[python] 실행 시 필요한 패키지 자동 설치  (0) 2022.01.01
[Python] FinanceDataReader 모듈  (0) 2021.07.31
728x90
반응형

목적

  • Maria DB를 구축하고 Sql 연습하는데 사용함
  • 나중에 개발할 크롤러 및 RPA 봇과 연계하여 정보를 수집하고 REST API 서버를 통해 Post, Get 할 예정임

구성

  • OS : CentOS 7 Minimals
  • DB : Maria DB
  • 장비 : 남는 노트북 활용

서버로 사용할 노트북과 라즈베리 파이


서버 설치

 


서버 설정

  • 시간 동기화

 

  • 네트워크 설정

 

  • 유저 생성

 

  • SSH 설치 및 설정

 

  • SELinux 해제

 

  • Firewall 해제

 

  • net-tools, iptables 설치

 

  • mariadb 설치

 

  • DB, User 생성 및 권한 부여

 

  • 라즈베리파이와 다이렉트 연결

 

  • 원격 접속 테스트

 

 

 

https://ksr930.tistory.com/42

 

centos, c++ MariaDB 연동 테스트 해보기 (Makefile)

회사에서 진행중인 프로젝트에서 오라클 DB 기반의 서버를 오픈소스 DB로 바꾸는 프로젝트를 진행하게 되어서 실제 소스에 적용하기전에 테스트 프로그램을 만들어서 컴파일 하는 작업을 해보

ksr930.tistory.com

 

https://jamanbbo.tistory.com/43

 

django REST framework로 간단한 api 만들기

django REST ramework (DRF)는 RESTful한 API를 쉽게 만들 수 있도록 해준다.  지금부터 DRF를 사용해 영화 리스트를 CRUD (Create,Read,Update,Delete) 할 수 있는 간단한 API를 만들어 볼 것이다. 혹시 REST..

jamanbbo.tistory.com

 

728x90
반응형
728x90
반응형

목적

  • 하노이의 탑 알고리즘을 가시화하여 이해를 쉽게함
  • 가시화된 알고리즘을 재귀 함수로 구현함
  • 구현할 함수는 아래 2개임 ( A탑에 위치한 원반 개수는 N)
  • int count_hanoi(int n) : A에서 C까지 N개의 원판을 이동시키는데 필요한 전체 개수
  • void hanoi(int n, int from, int to) : n번째 원판을 From에서 To로 이동시킴

N=3일 경우 탑의 모습

 


 

탑 이동 알고리즘 (Hanoi Function)

  • 하노이 탑의 이동을 재귀로 구현할 땐 아래 이미지의 이동 방식을 알면 됨

N=2 인 경우 이동하는 모습

 

  • N이 2보다 더 큰 경우도 가장 밑에 있는 N번째 원판과 그위의 나머지 원판으로 부분을 나누면,
    위와 같은 방식으로 이동이 가능함

N=3인 경우 최초의 이동

 

  • hanoi(2, A, B)와 hanoi(2, B, C)의 이동을 직접 나열해보면 아래와 같다

hanoi(2, A, B)
hanoi(2, B, C)

 

  • hanoi(n, from, to) 함수는 아래와 같은 규칙을 갖는다. 

hanoi 함수 원리


 

원판의 개수로 전체 이동 횟수 구하기 (Count_Hanoi Function)

  • 하노이 탑의 이동 횟수는 아래와 같은 형태의 수열을 이루고 있다.

  • 원판의 개수가 N일 때, 원판을 이동 시키는 횟수는 '2의 N제곱 -1' (2^n -1)
  • 제곱연산은 1 << N으로도 표현이 가능함 (비트연산)
    Ex) 0001 << 3 -> 1000(2), 8(10) 
    원판 개수 = 1 << N -1

 

소스 코드

 

  • 아래 코드에선 탑을 1~3으로 표현함.
#include<iostream>

using namespace std;

void count_hanoi(int n){
	cout << (1 << n) -1 << "\n";
}

void hanoi(int n, int from, int to) {
	if (n == 1){
		cout << from << " " << to << "\n";
	}else{
		hanoi(n - 1, from, 6 - from - to);
		cout << from << " " << to << "\n";
		hanoi(n - 1, 6 - from - to, to);
	}
}

int main() {
	int n;
	cin >> n;

	count_hanoi(n);
	hanoi(n, 1, 3);
    
	return 0;
}

 

결과

N=3 결과

728x90
반응형
728x90
반응형

1. 목적 및 구성

  • 상대 PC에 제어 명령을 보내는 마스터 프로그램(이하 A)과 받은 명령을 수행할 슬레이브 프로그램 (이하 B)이 존재함
  • A는 B가 전송한 모니터 화면을 그려줄 인터페이스를 가지고 있으며, 해당 화면 내에서의 상호작용을 B에게 전달
  • B는 최초 실행 시 서버에 자동으로 연결을 시도하며, 연결 후 대상 pc의 화면과 정보를 A에게 전달함
    이후 A에서 보내오는 명령을 수행함 (마우스, 키보드 입력, 단축키 요청 등)

 

2. 기능

  • 자동 연결
  • 모니터링
  • 대상 정보 수집
  • 원격 제어

 

3. 알고리즘

  • 전역 후킹
  • 키보드 마우스 이벤트 모듈
  • 화면 캡쳐 및 코덱 인코딩
  • 실시간 비동기 UDP 전송
  • json 파싱
  • 트레이아이콘, DLL 로드

 

4. 오픈소스  

  • FFMPEG
  • OpenCV
728x90
반응형
728x90
반응형

프로그래머스 SQL 고득점 Kit 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

-- 1. 모든 레코드 조회하기
SELECT * from animal_ins order by animal_id asc

-- 2. 역순 정렬하기
SELECT Name, datetime from animal_ins order by animal_id desc

-- 3. 아픈 동물 찾기
SELECT animal_id, name from animal_ins where intake_condition = "Sick" order by animal_id asc ;

-- 4. 어린 동물 찾기
SELECT animal_id, name from animal_ins where not intake_condition = "aged" order by animal_id ASC

-- 5. 동물의 아이디와 이름
SELECT animal_id, name from animal_ins order by animal_id asc

-- 6. 여러 기준으로 정렬하기
SELECT animal_id, name, datetime from animal_ins order by name asc, datetime desc

-- 7. 상위 n개 레코드
SELECT name from animal_ins order by datetime asc limit 1

 


 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

-- 1. 최댓값 구하기
SELECT datetime from animal_ins order by datetime desc limit 1

-- 2. 최솟값 구하기
SELECT min(datetime) from animal_ins

-- 3. 동물 수 구하기
SELECT count(animal_id) from animal_ins;

-- 4. 중복 제거하기
SELECT distinct(name) from animal_ins

 


 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

-- 1. 고양이와 개는 몇마리 있을까
SELECT animal_type, count(animal_id) as count from animal_ins group by animal_type order by animal_type asc

-- 2. 동명 동물 수 찾기
SELECT name, count(name) as count from animal_ins group by name having count(name) >= 2 order by name asc

-- 3. 입양 시작 구하기 (1)
select HOUR(datetime) as hour, count(datetime) as count 
from animal_outs 
group by hour having hour >= 9 and hour < 20
order by hour asc

-- 4. 입양 시각 구하기 (2)
SET @h = -1;
SELECT (@h := @h + 1) as hour,
(select count(hour(datetime)) from animal_outs where hour(datetime) = @h) as count
from animal_outs where @h < 23

 


 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

-- 1. 이름이 없는 동물의 아이디
SELECT animal_id from animal_ins where name is NULL

-- 2. 이름이 있는 동물의 아이디
SELECT animal_id from animal_ins where name is not null order by animal_id asc

-- 3. NULL 처리하기
SELECT animal_type, ifnull(name, "No name") as name, sex_upon_intake from animal_ins;

 


 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

-- 1. 없어진 기록 찾기
SELECT outs.animal_id, outs.name from animal_outs outs
left outer join animal_ins ins
on outs.animal_id = ins.animal_id
where ins.animal_id is null
order by outs.animal_id asc

-- 2. 있었는데요 없었습니다
SELECT ins.animal_id, ins.name from animal_ins ins
join animal_outs outs on ins.animal_id = outs.animal_id
where ins.datetime > outs.datetime
order by ins.datetime asc

-- 3. 오랜 기간 보호한 동물 (1)
select ins.name, ins.datetime from animal_ins ins
left join animal_outs outs 
on ins.animal_id = outs.animal_id
where outs.animal_id is null
order by ins.datetime asc
limit 3

-- 4. 보호소에서 중성화한 동물
SELECT ins.animal_id, ins.animal_type, ins.name from animal_ins ins
left join animal_outs outs
on ins.animal_id = outs.animal_id
where (outs.sex_upon_outcome like '%Spayed%' or outs.sex_upon_outcome like '%Neutered%')
and ins.sex_upon_intake like '%Intact%'
order by ins.animal_id asc

 


 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

-- 1. 루시와 엘라 찾기 
SELECT animal_id, name, sex_upon_intake from animal_ins
where name="Lucy" or name="Ella" or name="Pickle" or name="Rogan" or name="Sabrina" or name="Mitty"
order by animal_id asc

-- 2. 이름에 el이 들어가는 동물 찾기
SELECT animal_id, name from animal_ins
where lower(name) like "%el%" and animal_type = "Dog"
order by name asc

-- 3. 중성화 여부 파악하기
SELECT animal_id, name,
case when (SEX_UPON_INTAKE LIKE '%NEUTERED%' OR SEX_UPON_INTAKE LIKE '%SPAYED%')then 'O' else 'X' end
from animal_ins
order by animal_id asc

-- 4. 오랜 기간 보호한 동물 (2)
SELECT ins.animal_id, ins.name from animal_ins ins, animal_outs outs
where ins.animal_id = outs.animal_id
order by datediff(outs.datetime, ins.datetime) desc
limit 2

-- 5. DATETIME에서 DATE로 형 변환
SELECT animal_id, name, DATE_FORMAT(datetime, '%Y-%m-%d') as 날짜 from animal_ins
order by animal_id asc

 

728x90
반응형
728x90
반응형

1. 구분

  • DVD ISO 파일
  • Everything ISO
  • Minimal ISO

 

2. 네트워크 설정

  • vi /etc/sysconfig/network-scripts/ifcfg-enpXXX -> ONBOOT=YES, gateway, dns, ...
  • systemctl restart network or service network-manager restart
  • ip addr

 

3. 네트워크 관련 설치

  • yum -y install net-tools bind-tools nmap

 

4. 시간 동기화

  • yum -y install rdate
  • rdate -s time.bora.net
  • timedatectl set-ntp y
  • date

 

4. 유저 생성

  • adduser -m -u 10001 hwan
  • passwd hwan

 

5. ssh 설정

  • yum -y install openssh-server openssh-clients openssh-askpass
  • vi /etc/ssh/sshd_config
  • PermitRootLogin no
  • MaxAuthTries 3
  • MaxSessions 5
  • service sshd start
  • service sshd status

 

7. iptables 설정

  • yum -y install iptables-services
  • systemctl enable iptables
  • systemctl start iptables 
  • iptables -nL
  • iptables -A INPUT -d tcp --dport port -j ACCEPT

 

728x90
반응형
728x90
반응형

1. URL : https://www.acmicpc.net/workbook/view/1152

 

문제집: 삼성 SW 역량 테스트 기출 문제 (baekjoon)

 

www.acmicpc.net

 

2. 문제풀이

  • 구슬 탈출2 (골드1)
  • 2048(Easy) (골드2)
  • 뱀 (골드 5)
  • 시험 감독(브론즈 2)
#include <iostream>
#include <vector>
#include <cmath> 

using namespace std;

int main() {
	double n, tmp, b, c, sum=0;
	double sub_supervisor;

	cin >> n;
	vector<double> exam_room;

	for (int i = 1; i <= n; i++) {
		cin >> tmp;
		exam_room.push_back(tmp);
	}

	cin >> b >> c;

	for (auto exam : exam_room) {
        if (exam - b <= 0) continue;
		sum += ceil((exam - b) / c);
	}

	printf("%0.lf\n", sum + n);
    
    return 0;
}
  • 주사위 굴리기 (골드 4)

 

728x90
반응형
728x90
반응형

1. 개요

 - 라즈베리파이 재설치를 위해 공식 홈페이지에 접속했지만 iso 파일이 아닌 RaspberryPi OS Imager(exe)를 제공

 - 해당 툴을 사용하여 진행했지만 너무 느린 속도로 인해 설치가 제한됨

 - 직접 이미지 파일을 다운로드하여 Rufus를 이용하여 설치하기로함

 - 해당 방식으로 설치 시 ssh 활성화, wifi 연결 등의 작업을 미리해둘 수 없으므로, 별도의 인터페이스가 필요함

 - 2020-02-13 버전 이후로 파일이 없음 (최신버전 필요 시 Imager 활용)

 - 공식 홈페이지(https://www.raspberrypi.com/software/raspberry-pi-desktop/)에서 설치 시 iso 파일 다운로드 가능


2. 라즈베리 파이 OS 이미지 파일 다운로드

    ** 위 경로에서 아래와 같은 폴더를 찾기

 

  • raspbian full OS 선택

 

  • images 폴더 선택

 

  • 최신버전 선택 후 .zip 파일 다운로드

 


3. Rufus 포터블 다운로드

   ** 위 경로에서 아래 이미지와 같은 링크 찾기

 


4. micro SD 카드 연결 후 포맷

** 내용은 아래 사진과 다를 수 있음, 어댑터로 PC에 연결 > 해당 드라이브 우클릭 > 포맷 > 시작

 


5. 이미지 작성

** 다운로드 받은 zip 파일 압축해제 > img파일 획득

** 장치 선택 후 선택 버튼으로 해당 img 파일 선택

시작 클릭
완료

 


6. 확인

728x90
반응형
728x90
반응형

문제 1. 동전 0

  • 가장 금액이 큰 동전부터 개수를 세면서 k원에서 차감해줌
  • k가 0이되면 동전의 개수를 출력 
#include <iostream>
#include <map> 

using namespace std;

int main() {
	int n, k, tmp;
	map<int, int> m;
	map<int, int>::reverse_iterator reiter;

	cin >> n >> k;
	
	for (int i = 0; i < n; i++) {
		cin >> tmp;
		m[tmp] = 0;
	}

	for(reiter = m.rbegin(); reiter != m.rend(); reiter++) {
		while (reiter->first <= k) {
			m[reiter->first]++;
			k -= reiter->first;
		}

		if (k <= 0) break;
	}

	tmp = 0;
	for (reiter = m.rbegin(); reiter != m.rend(); reiter++) {
		if (reiter->second > 0) {
			tmp += reiter->second;
		}
	}

	cout << tmp << "\n";
    
    return 0;
}

 

문제 2. 회의실 배정

 

 

문제 3. ATM

#include <iostream>
#include <vector>
#include <algorithm> 

using namespace std;

int main() {
	int test_case;
	int a, sum=0;
	
	vector<int> v;

	cin >> test_case;

	for (int i = 0; i < test_case; i++) {
		cin >> a;
		v.push_back(a);
	}

	sort(v.begin(), v.end());

	for (int i = 0; i < test_case; i++) {
		for (int j = 0; j <= i; j++) {
			sum += v[j];
		}
	}

	cout << sum << "\n";
    
    return 0;
}

 

문제 4. 잃어버린 괄호

 

 

문제 5. 주유소

 

 

결과

728x90
반응형
728x90
반응형

문제 1. 피보나치 함수

  • 피보나치 f(n) 이 몇개의 f(0)과 f(1)로 이루어 져 있는지 출력하는 문제
  • 점화식(?) { f(i).first, f(i).second } = { f(i-1).first+f(i-2).first, f(i-1).second+f(i-2).second } 을 찾음
#include<iostream>
#include<vector>
#include<utility>

using namespace std;

int main() {
	int test_case;
	cin >> test_case;
	
	vector<pair<int, int>> f;

	f.push_back({ 1, 0 });
	f.push_back({ 0, 1 });

	for (int i = 2; i <= 40; i++) {
		f.push_back({f.at(i-1).first + f.at(i-2).first, f.at(i-1).second + f.at(i-2).second});
	}

	int* n = new int[test_case];
	for (int i = 0; i < test_case; i++) {
		cin >> n[i];
		cout << f.at(n[i]).first << " " << f.at(n[i]).second << "\n";
	}
    
    return 0;
}

 

문제 2. 신나는 함수 실행

 

문제 3. 01타일

 

문제 4. 파도반 수열

 

문제 5. RGB 거리

 

문제 6. 정수 삼각형

 

문제 7. 계단 오르기

 

문제 8. 1로 만들기

 

문제 9. 쉬운 계단 수

 

문제 10. 포도주 시식

 

문제 11. 가장 긴 증가하는 부분 수열

 

문제 12. 가장 긴 바이토닉 부분 수열

 

문제 13. 전깃줄

 

문제 14. LCS

 

문제 15. 연속합

 

문제 16. 평범한 배낭

 

결과

728x90
반응형
728x90
반응형

1. 문제

https://programmers.co.kr/learn/courses/30/lessons/43162

 

코딩테스트 연습 - 네트워크

네트워크란 컴퓨터 상호 간에 정보를 교환할 수 있도록 연결된 형태를 의미합니다. 예를 들어, 컴퓨터 A와 컴퓨터 B가 직접적으로 연결되어있고, 컴퓨터 B와 컴퓨터 C가 직접적으로 연결되어 있

programmers.co.kr

 

2. 접근 방식

  • 입력 받은 인접 행렬에 몇개의 그래프가 존재하는지를 묻는 문제
  • BFS를 수행 후에도 방문하지 않은 노드가 남아 있다면 다른 그래프가 존재한다고 판단함 (방문하지 않은 노드가 없을 때까지 반복하여 탐색)
  • 인접 행렬 형식의 2차원 Vector를 인접리스트 형식으로 변경 후 BFS 수행

 

3. 코드

#include <cstring>
#include <vector>
#include <queue>

using namespace std;

void bfs(int start, vector<int> *graph, bool* visited){
    queue<int> q;
    int nowNode;
    
    q.push(start);
    visited[start] = true;
    
    while(!q.empty()){
        nowNode = q.front();
        q.pop();
        
        for(auto node : graph[nowNode]){
            if(!visited[node]){
                q.push(node);
                visited[node] = true;
            }
        }
    }
}

int solution(int n, vector<vector<int>> computers) {
    int answer = 0;

    vector<int> *computer = new vector<int>[n+1];
    
    for(int i=0; i < n; i++){
        for(int j=0; j < n; j++){
            if(computers[i][j] == 1 && i != j){
                computer[i+1].push_back(j+1);
            }
        }
    }
    
    
    bool *visited = new bool[n + 1];
    memset(visited, 0, sizeof(bool) * (n+1));

    for(int i=1; i<n+1; i++){
        if(!visited[i]){
            bfs(i, computer, visited);
            answer++;
        }
    }
    
    return answer;
}

 

4. 결과

728x90
반응형
728x90
반응형

1. 문제 (레벨 2)

https://programmers.co.kr/learn/courses/30/lessons/43165

 

코딩테스트 연습 - 타겟 넘버

n개의 음이 아닌 정수들이 있습니다. 이 정수들을 순서를 바꾸지 않고 적절히 더하거나 빼서 타겟 넘버를 만들려고 합니다. 예를 들어 [1, 1, 1, 1, 1]로 숫자 3을 만들려면 다음 다섯 방법을 쓸 수

programmers.co.kr

 

2. 접근 방식

  • BFS/ DFS 카테고리에 있는 문제지만, 해당 탐색 알고리즘으로 해결할 방법이 떠오르지 않아 완전탐색으로 구현
  • +, - 부호를 이진수로 표현하여 모든 경우에 대해 연산한 뒤 개수를 카운팅함
  • 통과는 했지만 메모리와 시간에 제한이 있다면 실패할 듯 함

 

3. 코드

def solution(numbers, target):
    answer = 0
    aa = pow(2, len(numbers))
    
    list_tmp = []
    list_arr = []
    
    for n in range(0, aa):
        tmp = n
        list_tmp = []
        
        while tmp > 0:
            list_tmp.append(tmp%2)
            tmp //= 2
            
        while len(list_tmp) < len(numbers):
            list_tmp.append(0)
         
        list_arr.append(list(reversed(list_tmp)))
        
        
    int_sum = 0    
    for tmp in list_arr:      
        int_sum = 0  
        
        for i in range(0, len(numbers)):
            if tmp[i]:
                int_sum += -1*numbers[i]
            else:
                int_sum += numbers[i]
        
        if int_sum == target:
            answer += 1
          
    
    return answer

 

4. 결과

 

728x90
반응형
728x90
반응형

문제 1. DFS와 BFS

#include <iostream>
#include <vector>
#include <algorithm> 
#include <cstring> 
#include <queue> 

using namespace std;

void func_1260_dfs_recursion(int n, vector<int> * graph, bool* visited) {
	visited[n] = true;
	cout << n << " ";

	for (auto node : graph[n]) {
		if (!visited[node]) {
			func_1260_dfs_recursion(node, graph, visited);
		}
	}
}

void func_1260_bfs_queue(int n, vector<int> * graph, bool* visited) {
	queue<int> q;
	int now_node;

	visited[n] = true;
	q.push(n);

	while (!q.empty()) {
		now_node = q.front();
		q.pop();
		cout << now_node << " ";

		for (auto node : graph[now_node]) {
			if (!visited[node]) {
				visited[node] = true;
				q.push(node);
			}
		}
	}
	cout << "\n";
}

int main() {
	int n, m, start_node, u, v;
	
	cin >> n >> m >> start_node;

	vector<int> *graph = new vector<int>[n+1];

	bool *visited = new bool[n+1];
	memset(visited, 0, sizeof(bool) * (n+1));

	for (int i = 0; i < m; i++) {
		cin >> u >> v;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}

	for (int i = 1; i <= n; i++) {
		sort(graph[i].begin(), graph[i].end());
	}
    
	func_1260_dfs_recursion(start_node, graph, visited);
	cout << "\n";

	memset(visited, 0, sizeof(bool) * (n + 1));
	func_1260_bfs_queue(start_node, graph, visited);
    
	return 0;
}

 

문제 2. 바이러스

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm> 

using namespace std;

static int func_2606_cnt;

void func_2606_dfs(int start, vector<int> *graph, bool* visited) {
	visited[start] = true;

	func_2606_cnt++;

	for (auto node : graph[start]) {
		if (!visited[node]) {
			func_2606_dfs(node, graph, visited);
		}
	}
}

int main() {
	int n, m, u, v;

	cin >> n >> m;

	vector<int> *graph = new vector<int>[n+1];

	bool* visited = new bool[n+1];
	memset(visited, 0, sizeof(bool) * (n+1));

	func_2606_cnt = 0;

	for (int i = 0; i < m; i++) {
		cin >> u >> v;
		
		graph[u].push_back(v);
		graph[v].push_back(u);
	}

	for (int i = 1; i <= n; i++) {
		sort(graph[i].begin(), graph[i].end());
	}
    
	func_2606_dfs(1, graph, visited);

	cout << func_2606_cnt -1 << "\n";
    
	return 0;
}

 

문제 3. 단지 번호 붙이기

#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<utility> 

using namespace std;

int func_2667_bfs(int cnt, int n, queue<pair<int, int>> q, int **map, int ** v) {
	int _x, _y, a=0;
	pair<int, int> now, tmp;

	int** direc = new int* [4];
	for (int i = 0; i < 4; i++) {
		direc[i] = new int[2];
		if (i == 0) {
			_x = 0;
			_y = -1;
		}
		else if (i == 1) {
			_x = 1;
			_y = 0;
		}
		else if (i == 2) {
			_x = 0;
			_y = 1;
		}
		else if (i == 3) {
			_x = -1;
			_y = 0;
		}
		direc[i][0] = _x;
		direc[i][1] = _y;
	}

	while (!q.empty()) { 
		now = q.front();
		q.pop();
		if (v[now.first][now.second] != 1) {
			v[now.first][now.second] = 1;
			a++;
		}

		for (int i = 0; i < 4; i++) {
			_x = now.first + direc[i][0];
			_y = now.second + direc[i][1];

			if (_x < 0 || _x >= n) {
				continue;
			}
			if (_y < 0 || _y >= n) {
				continue;
			}
			
			if (map[_x][_y] == 0) {
				continue;
			}

			if (v[_x][_y] == 1) {
				continue;
			}

			// 방문한적 없는 좌표인데 값이 1보다 크면 현재 카운트로 덮어쓰기 및 방문처리
			if (map[_x][_y] >= 1) {
				v[_x][_y] = 1;
				map[_x][_y] = cnt;
				q.push({_x, _y});
				//cout << _x << ", " << _y << "\n";
				a++;
			}
		}
	}

	for (int i = 0; i < 4; i++) {
		delete direc[i];
	}

	return a;
}

int main() {
	int n, cnt =0;
	string str;
	queue<pair<int, int>> q;
	vector<int> m;
	int tmp_m;

	cin >> n;

	int** v = new int* [n];
	for (int i = 0; i < n; i++) {
		v[i] = new int[n];
		for (int j = 0; j < n; j++) {
			v[i][j] = 0;
		}
	}

	int** _map = new int* [n];
	for (int i = 0; i < n; i++) {
		str = "";
		_map[i] = new int[n];

		cin >> str;
		for (int j = 0; j < n; j++) {
			_map[i][j] = str[j] - '0';
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (_map[i][j] == 1) {
				q.push({ i, j });
				
				tmp_m = func_2667_bfs(cnt+1, n, q, _map, v);
				if (tmp_m != 0) {
					m.push_back(tmp_m);
					cnt++;
				}
			}
			
		}
	}

	sort(m.begin(), m.end());

	cout << cnt << "\n";
	for (int i = 0; i < cnt; i++) {  
		cout << m[i] << "\n";
	}
    return 0;
}

 

문제 4. 유기농 배추

#include <iostream>
#include <utility>
#include <cstring>
#include <queue> 

using namespace std;

int main() {
	int test_case;
	int n, m, k;
	int u, v;
	int _x, _y;
	pair<int, int> dir[4] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} }; // 상, 우, 하, 좌
	pair<int, int> tmp_q;
	int graph_count = 0;

	int** _map;
	int** _visit;
	queue<pair<int, int>> q;


	cin >> test_case;
	for (int a = 0; a < test_case; a++) {
		cin >> m >> n >> k;

		// Map 생성 및 초기화
		_map = new int* [n];
		_visit = new int* [n];

		for (int i = 0; i < n; i++) {
			_map[i] = new int[m];
			_visit[i] = new int[m];

			memset(_map[i], 0, sizeof(int) * m);
			memset(_visit[i], 0, sizeof(int) * m);

		}

		// Map 업데이트
		for (int i = 0; i < k; i++) {
			cin >> u >> v;
			_map[v][u] = 1;
		}

		graph_count = 0;


		// Map 탐색
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {

				// 지도에서 현재 좌표가 1이고 방문한 적이 없으면 현재 좌표를 q에 등록하고 방문 처리
				if (_map[i][j] == 1 && _visit[i][j] != 1) {
					q.push({i, j});
					_visit[i][j] = 1;
					
					graph_count++;
				}

				// q에 값이 있으면
				while (!q.empty()) {
					tmp_q = q.front();
					q.pop();
					
					// 현재 좌표에서 인접한 4방향 좌표를 검사, 위부터 시계방향
					for (int i = 0; i < 4; i++) {
						_x = tmp_q.first + dir[i].first;
						_y = tmp_q.second + dir[i].second;

						// 경계선 검사
						if (_x >= n || _x < 0)
							continue;

						if (_y >= m || _y < 0) 
							continue;

						// 값 검사
						if (_map[_x][_y] == 0)
							continue;
						
						// 방문여부 검사
						if (_visit[_x][_y] == 1)
							continue;

						// 방문기록 남기고 다음 작업대상에 추가
						_visit[_x][_y] = 1;
						q.push({_x, _y});
					}
				}
			}
		}

		cout << graph_count << "\n";

		// 메모리 해제
		for (int i = 0; i < n; i++) {
			free(_map[i]);
			free(_visit[i]);
		}
	}
    
    return 0;
}

 

문제 5. 미로 탐색

#include<iostream>
#include<queue>
#include<cstring>

using namespace std;

// 노드 정보 저장용 클래스
class func_2178_node {
public:
	int x;
	int y;
	int value;
	int visited;
};

int func_2178_BFS(int n, int m, func_2178_node **_map, int *start_node, int *end_node) {
	// BFS 탐색을 위한 큐 생성 현재 노드 저장
	queue<func_2178_node> q;
	func_2178_node tmp_node, now_node;

	// 상0, 우1, 하2, 좌3 
	int** direction = new int*[4];
	for (int i = 0; i < 4; i++) {
		direction[i] = new int[2];

		if (i == 0) {
			direction[i][0] = 0;
			direction[i][1] = -1;
		}
		if (i == 1) {
			direction[i][0] = 1;
			direction[i][1] = 0;
		}
		if (i == 2) {
			direction[i][0] = 0;
			direction[i][1] = 1;
		}
		if (i == 3) {
			direction[i][0] = -1;
			direction[i][1] = 0;
		}
	}


	// 시작노드의 방문 여부 변경
	_map[start_node[0]][start_node[1]].visited = 1;
	// 시작노드 넣기
	q.push(_map[start_node[0]][start_node[1]]);

	// 큐에 값이 있으면 탐색 시작
	while (!q.empty()) {
		// 현재 큐의 값 가져오기 + pop
		now_node = q.front();
		q.pop();

		// 인접 노드 탐색 (시계방향으로 탐색)
		for (int i = 0; i < 4; i++) {
			// 현재 좌표가 좌우를 넘어가는지 확인
			if (now_node.x + direction[i][0] <= 0 || now_node.x + direction[i][0] > n) {
				continue;
			}

			// 현재 좌표가 상하를 넘어가는지 확인
			if (now_node.y + direction[i][1] <= 0 || now_node.y + direction[i][1] > m) {
				continue;
			}

			// 이동한 값이 맵 안에 있으면 노드 이동
			tmp_node = _map[now_node.x + direction[i][0]][now_node.y + direction[i][1]];

			// 값이 1이 아닌지 검사, 아니면 continue;
			if (tmp_node.value == 0) {
				continue;
			}

			// 방문 여부가 없는지 검사 (방문했으면 다음거)
			if (tmp_node.visited) {
				continue;
			}

			_map[tmp_node.x][tmp_node.y].visited = _map[now_node.x][now_node.y].visited + 1;
			q.push(_map[tmp_node.x][tmp_node.y]);
		}
	}

	return _map[n][m].visited;
}

int main() {
	int n, m;
	int* start_node = new int[2];
	int* end_node = new int[2];
	string str_input;

	cin >> n >> m;

	start_node[0] = 1;
	start_node[1] = 1;
	end_node[0] = n;
	end_node[1] = m;

	func_2178_node** map = new func_2178_node*[n+1];
	for (int i = 1; i <= n; i++) {
		map[i] = new func_2178_node[m+1];
	}

	for (int i = 1; i <= n; i++) {
		cin >> str_input;
		for (int j = 1; j <= m; j++) {
			map[i][j].x = i;
			map[i][j].y = j;
			map[i][j].value = str_input[j-1] - '0';
			map[i][j].visited = 0;
		}
	}

	cout << func_2178_BFS(n, m, map, start_node, end_node) << "\n";

    return 0;
}

 

문제 6. 토마토

#include <iostream>
#include <queue> 

using namespace std;

class func_7576_tomato {
public:
	int x;
	int y;
	int visited;
	int value;
};

void func_7576_bfs(int n, int m, func_7576_tomato** box, queue<func_7576_tomato> q) {
	func_7576_tomato now_tomato, tmp_tomato;

	// 방향 정의 (시계방향)
	int** direc = new int*[4];
	int _x, _y;
	for (int i = 0; i < 4; i++) {
		direc[i] = new int[2];

		// 상
		if (i == 0) {
			_x = 0;
			_y = -1;
		}
		// 우
		if (i == 1) {
			_x = 1;
			_y = 0;
		}
		// 하
		if (i == 2) {
			_x = 0;
			_y = 1;
		}
		// 좌
		if (i == 3) {
			_x = -1;
			_y = 0;
		}

		direc[i][0] = _x;
		direc[i][1] = _y;
	}

	// bfs 탐색 시작 
	while (!q.empty	()) {
		now_tomato = q.front();
		q.pop();

		// 각 방향별 탐색
		for (int i = 0; i < 4; i++) {
			// 이동한 범위가 토마토 상자 내부인지 검사 (x축)
			if (now_tomato.x + direc[i][0] < 0 || now_tomato.x + direc[i][0] >= n) {
				continue;
			}
			// 이동한 범위가 토마토 상자 내부인지 검사 (y축)
			if (now_tomato.y + direc[i][1] < 0 || now_tomato.y + direc[i][1] >= m) {
				continue;
			}

			tmp_tomato = box[now_tomato.x + direc[i][0]][now_tomato.y + direc[i][1]];

			// 해당 위치가 벽인지 검사
			if (tmp_tomato.value != 0) {
				continue;
			}

			// 해당 위치에 숙성되지 않은 토마토가 있으면 숙성 시키고 몇 일차에 숙성시켰는지 입력 후 큐에 등록
			box[tmp_tomato.x][tmp_tomato.y].value = 1;
			box[tmp_tomato.x][tmp_tomato.y].visited = now_tomato.visited + 1;
			q.push(box[tmp_tomato.x][tmp_tomato.y]);
		}
	}
}

int main() {
	int m, n, tmp, max;
	queue<func_7576_tomato> q;

	// 노드 개수
	cin >> m >> n;

	// 노드 생성
	func_7576_tomato** box = new func_7576_tomato*[n];
	for (int i = 0; i < n; i++) {
		box[i] = new func_7576_tomato[m];
	}

	// 초기화
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			box[i][j].x = i;
			box[i][j].y = j;
			box[i][j].visited = 0;
			box[i][j].value = 0;
		}
	}

	// 입력값 받기, 입력에 따른 값 설정
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> tmp;
			box[i][j].value = tmp;
			
			//입력 값이 1이면 큐에 등록
			if (tmp == 1) {
				q.push(box[i][j]);
			}
		}
	}

	func_7576_bfs(n, m, box, q);

	max = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			// 숙성안된 토마토가 있으면 -1
			if (box[i][j].value == 0) {
				max = -1;
				break;
			}
			// 최대값 찾아서 갱신
			if (max < box[i][j].visited) {
				max = box[i][j].visited;
			}
		}
		if (max == -1) {
			break;
		}
	}

	cout << max << "\n";
    
	return 0;
}

 

문제 7. 토마토

 

문제 8. 숨바꼭질

#include<iostream>
#include<queue>
#include<cstring>

using namespace std;

void func_1697_bfs(int k, queue<int> q, int *visited) {
    int now;
    while (!q.empty()) {
        now = q.front();
        q.pop(); 

        if (now == k) {
            break;
        }

        if (visited[now - 1] == 0 && (now - 1) >= 0) {
            visited[now - 1] = visited[now] + 1;
            q.push(now-1);
        }

        if ( (now+1) < 100000 && visited[now + 1] == 0) {
            visited[now + 1] = visited[now] + 1;
            q.push(now+1);
        }
        
        if ( (now * 2) <= 100000 && visited[now * 2] == 0) {
                visited[now * 2] = visited[now] + 1;
                q.push(now * 2);
        }
    }
}

int main() {
    int n, k;
    cin >> n >> k;
    
    int* visited = new int[100000];
    memset(visited, 0, sizeof(int) * 100000);
    queue<int> q;

    q.push(n);
    visited[n] = 1;
    func_1697_bfs(k, q, visited);

    cout << visited[k]-1 << "\n";
    
    return 0;
}

 

문제 9. 벽 부수고 이동하기

 

문제 10. 나이트의 이동

 

문제 11. 이분 그래프

 

결과

728x90
반응형
728x90
반응형

목적

  • 탐색 알고리즘에서 사용되는 표현 방식을 이해하고 직접 구현
  • 탐색 알고리즘인 DFS(Depth First Search, 깊이 우선 탐색) 알고리즘에 대해 이해하고 직접 구현
  • 탐색 알고리즘인 BFS(Breadth First Search, 너비 우선 탐색) 알고리즘에 대해 이해하고 직접 구현

인접리스트와 인접 행렬

그래프

위 와 같은 그래프가 있을 때, 이 그래프를 표현하는 방식은 크게 2가지(인접리스트, 인접행렬)가 있다.

각 표현 방식을 구현해보면 다음 코드와 같다.

 

1) 간선을 인접리스트로 변환

#include<iostream>
#include<cstring>
#include<vector>
#include<map>

using namespace std;

// 만들어진 그래프를 출력
void print_adjacency_list(map<int, vector<int>> graph) {
	for (auto node : graph) {
		cout << node.first << " : ";
		for (auto ns : node.second) {
			cout << ns << " ";
		}
		cout << "\n";
	}
}

int main() {
	int n, m, u, v;
	
        // 최초 입력 받기
	cin >> n >> m >> start_node;

	// 그래프를 인접리스트 형식으로 표현
	map<int, vector<int>> graph;

	// 간선의 개수만큼 노드에 추가
	for (int i = 0; i < m; i++) {
		cin >> u >> v;
        
		// 각 노드별로 연결된 간선을 서로 추가(무방향 또는 양방향 그래프)
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
    
    // 생성된 인접리스트 출력
    print_adjacency_list(graph);
    
    return 0;
}

출력 결과

 

2) 간선을 인접행렬로 변환

#include<iostream>

using namespace std;

int main() {
	int n, m, u, v;

	cin >> n >> m;

	// 인접행렬 생성
	int** graph = new int* [n];
	for (int i = 0; i < n; i++) {
		graph[i] = new int[n];
	}

	// 인접행렬 초기화
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			graph[i][j] = 0;
		}
	}

	// 간선 입력
	for (int i = 0; i < m; i++) {
		cin >> u >> v;
        
		u--;
		v--;
        
		// 무방향 그래프
		graph[u][v] = graph[v][u] = 1;
	}


	// 인접행렬 출력
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cout << graph[i][j] << " ";
		}
		cout << "\n";
	}
    
	return 0;
}

출력 결과

 

3) 인접행렬을 문자열로 입력받기

#include<iostream>

using namespace std;

int main() {
	int n;
	string str;

	cin >> n;

	int** map = new int* [n];
	for (int i = 0; i < n; i++) {
		str = "";
		map[i] = new int[n];

		cin >> str;
		for (int j = 0; j < str.length(); j++) {
			map[i][j] = str[j] - '0';
		}
	}
	
	for (int i = 0; i < n; i++) {
		for (int j = 0; j< n; j++) {
			cout << map[i][j];
		}
		cout << "\n";
	}
    
	return 0;
}

출력 결과

 

4) 인접행렬을 인접리스트로 변환

#include<iostream>
#include<vector>

using namespace std;

vector<int> *Convert_adjMatrix_to_adjList(int n, int** matrix) {
	vector<int> * adjlist = new vector<int>[n+1];

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (matrix[i][j] == 1 && i != j) {
				adjlist[i+1].push_back(j+1);
			}
		}
        sort(adjlist[i+1].begin(), adjlist[i+1].end());
	}

	return adjlist;
}

int main() {
	int n;
	string str;

	cin >> n;

	int** map = new int* [n];
	for (int i = 0; i < n; i++) {
		str = "";
		map[i] = new int[n];

		cin >> str;
		for (int j = 0; j < str.length(); j++) {
			map[i][j] = str[j] - '0';
		}
	}

	vector<int> *adl = Convert_adjMatrix_to_adjList(n, map);

	for (int i = 1; i <= n; i++) {
		cout << i << " : ";
		for (auto node : adl[i]) {
			cout << node << " ";
		}
		cout << "\n";
	}
    
	return 0;
}

출력 결과

 


DFS (깊이 우선 탐색)

1 2 4 3 5

 

  • 재귀로 DFS 구현
#include<iostream>
#include<cstring>
#include<vector>
#include<map>

using namespace std;

void dfs_recursion(int n, vector<int>* graph, bool* visited) {
	cout << "start\nCurrent Node : " << n <<  "";

	// 시작노드의 방문 여부를 체크
	visited[n] = true;

	for (auto node : graph[n]) {
		cout << "\nN : " << n << ", Node : " << node << ", Visited : " << visited[node] << " ";
		// 노드가 방문이 되어있는지 확인
		if (!visited[node]) {
			cout << "-> Next node : " << node << "\n";
            
			// 방문 안된 노드의 키값을 넣음
			func_1260_dfs_recursion(node, graph, visited);
		}
	}
	cout << "\nend";
}

int main() {
	int n, m, start_node, u, v;
	
	cin >> n >> m >> start_node;

	vector<int> *graph = new vector<int>[n+1];
    
	bool *visited = new bool[n+1];
	memset(visited, 0, sizeof(bool) * (n+1));

	for (int i = 0; i < m; i++) {
		cin >> u >> v;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}

	/*
	// 오름차순으로 각 벡터를 정렬시킴 (이부분 주석 해제 시 1 2 3 4 5 순서로 진행)
	for (int i = 1; i <= n; i++) {
		sort(graph[i].begin(), graph[i].end());
	}
	*/

	dfs_recursion(start_node, graph, visited);
    
    return 0;
}

재귀 방식 코드 결과

 

  • 스택으로 DFS 구현
//

 


 

BFS (너비 우선 탐색)

1 2 5 3 4

 

  • 큐로 BFS 구현
#include<iostream>
#include<cstring>
#include<vector>
#incldue<queue>

using namespace std;

void bfs_queue(int n, vector<int> * graph, bool* visited) {
	queue<int> q;
	int now_node;

	visited[n] = true;
	q.push(n);

	while (!q.empty()) {
		now_node = q.front();
		q.pop();
		cout << now_node << " ";

		for (auto node : graph[now_node]) {
			if (!visited[node]) {
				visited[node] = true;
				q.push(node);
			}
		}
	}
	cout << "\n";
}

int main() {
	int n, m, start_node, u, v;
	
	cin >> n >> m >> start_node;

	vector<int> *graph = new vector<int>[n+1];

	bool *visited = new bool[n+1];
	memset(visited, 0, sizeof(bool) * (n+1));

	for (int i = 0; i < m; i++) {
		cin >> u >> v;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}

	for (int i = 1; i <= n; i++) {
		sort(graph[i].begin(), graph[i].end());
	}


	bfs_queue(start_node, graph, visited);
    
    return 0;
}

출력 결과

 

728x90
반응형
728x90
반응형

1. 목적

  • WPF에서 OpenCV를 활용하여 기본 WPF 컨트롤인 Image에 노트북 (또는 USB) 카메라에서 가져온 영상을 Bitmap 형식으로 그려줌
  • 환경 구축 및 빌드는 https://hwan001.tistory.com/144?category=836235 링크 참조

 

2. 코드 (Xaml)

<Window x:Class="WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF"
        Loaded="windows_loaded"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="600">
    <Grid>
        <Image Name="Cam_1" Margin="20,20,20,100"/>
    </Grid>
</Window>

 

3. 코드 (C#)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// OpenCV 사용을 위한 using
using OpenCvSharp;
using OpenCvSharp.WpfExtensions;

// Timer 사용을 위한 using
using System.Windows.Threading;

namespace WPF
{
    // OpenCvSharp 설치 시 Window를 명시적으로 사용해 주어야 함 (window -> System.Windows.Window)
    public partial class MainWindow : System.Windows.Window
    {
    	// 필요한 변수 선언
        VideoCapture cam;
        Mat frame;
        DispatcherTimer timer;
        bool is_initCam, is_initTimer;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void windows_loaded(object sender, RoutedEventArgs e)
        {
            // 카메라, 타이머(0.01ms 간격) 초기화
            is_initCam = init_camera();
            is_initTimer = init_Timer(0.01); 

            // 초기화 완료면 타이머 실행
            if(is_initTimer && is_initCam) timer.Start();
        }

        private bool init_Timer(double interval_ms)
        {
            try
            {
                timer = new DispatcherTimer();

                timer.Interval = TimeSpan.FromMilliseconds(interval_ms);
                timer.Tick += new EventHandler(timer_tick);

                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool init_camera() {
            try {
                // 0번 카메라로 VideoCapture 생성 (카메라가 없으면 안됨)
                cam = new VideoCapture(0);
                cam.FrameHeight = (int)Cam_1.Height;
                cam.FrameWidth = (int)Cam_1.Width;

                // 카메라 영상을 담을 Mat 변수 생성
                frame = new Mat();

                return true;
            }catch{
                return false;
            }
        }

        private void timer_tick(object sender, EventArgs e)
        {
            // 0번 장비로 생성된 VideoCapture 객체에서 frame을 읽어옴
            cam.Read(frame);
            // 읽어온 Mat 데이터를 Bitmap 데이터로 변경 후 컨트롤에 그려줌
            Cam_1.Source = OpenCvSharp.WpfExtensions.WriteableBitmapConverter.ToWriteableBitmap(frame);
        }
    }
}

 

 

4. 결과

결과

728x90
반응형
728x90
반응형

1. 설치 목적

  • WPF에서 OpenCV 최신 버전(2022년 2월 2일 기준) 기능 사용

 

2. 주의점

  • OpenCVSharp4는 여러개의 Nuget으로 나워져 있음
  • 한 개라도 없으면 함수 또는 자료형의 일부를 찾을 수 없음

 

3. 설치 (Nuget Package Manager)


- WPF 환경에서 사용하기 위해 초록색 박스 부분 (OpenCvSharp4, OpenCvSharp4.runtime.win, OpenCvSharp4.WpfExtentions) 설치

- 윈도우 환경이라면 빨간색 박스 부분 설치가 더 간편함 (OpenVcSharp4.Windows)

 

 

4. OpenVcSharp4.Windows (빨간 박스) 설치 완료

참조

 

728x90
반응형
728x90
반응형

문제 1. 수 정렬하기 (브론즈 1)

  • vector로 입력 받아 sort로 정렬
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main() {
	int a, num;
	vector<int> v;
    
	cin >> a;
	
	for (int i = 0; i < a; i++) {
		cin >> num;
		v.push_back(num);
	}

	sort(v.begin(), v.end());

	for (int i = 0; i < v.size(); i++) {
		cout << v.at(i) << "\n";
	}
    
    return 0;
}

 

문제 2. 수 정렬하기 2 (실버 5)

  • vector로 입력 받고 sort로 정렬 (1번과 동일)
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main() {
	int a, num;
	vector<int> v;
    
	cin >> a;
	
	for (int i = 0; i < a; i++) {
		cin >> num;
		v.push_back(num);
	}

	sort(v.begin(), v.end());

	for (int i = 0; i < v.size(); i++) {
		cout << v.at(i) << "\n";
	}
    
    return 0;
}

 

문제 3. 수 정렬하기 3 (실버 5)

  • map에 입력 받은 수의 개수를 카운팅함
#include<iostream>
#include<map>

using namespace std;

int main() {
    cin.tie(NULL);
    cin.sync_with_stdio(false);
    
	int a, num;
	map<int, int> m;
	map<int, int>::iterator iter;
	cin >> a;

	for (int i = 0; i < a; i++) {
		cin >> num;
		if (m[num] == 0) m[num] = 1;
		else m[num]++;
	}

	for (iter = m.begin(); iter != m.end(); iter++) {
		for (int i = 0; i < iter->second; i++) {
			cout << iter->first << "\n";
		}
	}
    return 0;
}

 

문제 4. 통계학 (실버 4)

  • 문제 자체는 어렵지 않지만, 함정이 많은 문제였음
  • 평균값이 -1과 0 사이에 존재할 경우 별도의 연산이 없으면 -0으로 출력되는 문제가 존재
  • 최빈값(가장 많이 나온 값)을 구하고 여러개 일 경우 2번째로 작은 값을 구하는 부분 구현
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<numeric>

using namespace std;

int main() {
	int a;
	double tmp, sum, aver, max, min_val, max_val;

	cin >> a;
	map<double, int> m;
	vector<double> v, v_mode;

	sum = 0;
	for (int i = 0; i < a; i++) {
		cin >> tmp;

		v.push_back(tmp);

		if (m[tmp] == 0) {
			m[tmp] = 1;
		}
		else {
			m[tmp]++;
		}

		sum += tmp;
	}

	aver = accumulate(v.begin(), v.end(), 0.0) / v.size();
	printf("%.0f\n", aver<=0&&aver>-1?(int)aver:aver);

	int cnt = 0;
	int index = (int) floor(a / 2);
	sort(v.begin(), v.end());
	cout << v.at(index) << "\n";

	max = 0;
	for (auto num : m) {
		if (num.second > max) {
			max = num.second;
		}
	}
    
	cnt = 0;
	for (auto num : m) {
		if (num.second == max) {
			v_mode.push_back(num.first);
		}
	}
	
	if (v_mode.size() > 1) {
		sort(v_mode.begin(), v_mode.end());
		cout << v_mode.at(1) << "\n";
	}
	else
	{
		cout << v_mode.at(0) << "\n";
	}

	min_val = v.at(0);
	max_val = v.at(v.size() - 1);
	cout << max_val - min_val << "\n";
    
	return 0;
}

 

문제 5. 소트인사이드 (실버 5)

  • vector로 입력받고 오름차순 정렬 후 역으로 출력(내림차순 정렬)
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

int main() {
	vector<char> v;
	string str;
	cin >> str;

	for (int i = 0; i < str.length(); i++) {
		v.push_back(str[i]);
	}

	sort(v.begin(), v.end());
	reverse(v.begin(), v.end());

	for (auto v_tmp : v) {
		cout << v_tmp;
	}
    
	return 0;
}

 

문제 6. 좌표 정렬하기 (실버 5)

  • x좌표로 정렬 후 y좌표 기준 정렬
#include <iostream>
#include <vector>
#include <utility> 
#include <algorithm> 

using namespace std;

int main() {
	int a, b, test_case;
	vector<pair<int, int>> v; 

	cin >> test_case;
	for (int i = 0; i < test_case; i++) {
		cin >> a >> b;
		v.push_back({a, b});
	}

	sort(v.begin(), v.end());

	for (auto v_tmp : v) {
		cout << v_tmp.first << " "  << v_tmp.second << "\n";
	}
    
    return 0;
}

 

문제 7. 좌표 정렬하기 2 (실버 5)

  • y좌표로 정렬 후 x좌표로 정렬
  • 문제 6번의 코드에서 입력 받는 순서와 출력 받는 순서만 반대로 해줌
#include <iostream>
#include <vector>
#include <utility> 
#include <algorithm> 

using namespace std;

int main() {
	int a, b, test_case;
	vector<pair<int, int>> v; 

	cin >> test_case;
	for (int i = 0; i < test_case; i++) {
		cin >> a >> b;
		v.push_back({b, a});
	}

	sort(v.begin(), v.end());

	for (auto v_tmp : v) {
		cout << v_tmp.second << " " << v_tmp.first << "\n";
	}
    
    return 0;
}

 

문제 8. 단어 정렬 (실버 5)

  • 문자열의 길이로 먼저 정렬 (map으로 받으면 알아서 오름차순)
  • 같은 길이의 문자열을 vector<string>에 받아서 따로 정렬하고 중복은 제거
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm> 
#include <map> 

using namespace std;

int main() {
	map<int, vector<string>> m;
	int test_case, str_len, str_len_max=0;
	string str;
	cin >> test_case;

	for (int i = 0; i < test_case; i++) {
		cin >> str;
		str_len = str.length();
		m[str_len].push_back(str);
		if (str_len > str_len_max)	str_len_max = str_len;
	}

	for (int i = 1; i <= str_len_max; i++) {
		sort(m[i].begin(), m[i].end());
		m[i].erase(unique(m[i].begin(), m[i].end()), m[i].end());
	}

	for (int i = 1; i <= str_len_max; i++) {
		for (auto v : m[i]) {
			cout << v << "\n";
		}
	}
    
    return 0;
}

 

문제 9. 나이순 정렬 (실버 5)

  • 위 문제와 비슷하게 map의 키값을 나이로 받고 이름을 vector로 받아 입력받은 순서로 출력
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm> 
#include <map> 

using namespace std;

int main() {
    int test_case;
	cin >> test_case;

	int age;
	string name;
	map<int, vector<string>> m;

	for (int i = 0; i < test_case; i++) {
		cin >> age >> name;
		m[age].push_back(name);
	}

	for (auto m_tmp : m) {
		for (auto m_name : m_tmp.second) {
			cout << m_tmp.first << " " << m_name << "\n";
		}
	}
    return 0;
}

 

문제 10. 좌표 압축 (실버 2)

  • 좌표를 입력받은 순서로 기록할 vector와 해당 좌표의 압축값을 기록한 map을 활용
#include <iostream>
#include <vector>
#include <algorithm> 
#include <map>

using namespace std;

int main(){
    int test_case;
	cin >> test_case;

	int tmp;
	map<int, int> m;
	vector<int> v_origin;

	for (int i = 0; i < test_case; i++) {
		cin >> tmp;
		v_origin.push_back(tmp);
	}

    
	vector<int> v_sort(v_origin);
	sort(v_sort.begin(), v_sort.end());
	v_sort.erase(unique(v_sort.begin(), v_sort.end()), v_sort.end());

	for (int i = 0; i < v_sort.size(); i++) {
		m[v_sort[i]] = i;
	}

	for (auto v_tmp : v_origin) {
		cout << m[v_tmp] << " ";
	}
    
	return 0;
}

 

결과

728x90
반응형
728x90
반응형

1. 문제 

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

 

1011번: Fly me to the Alpha Centauri

우현이는 어린 시절, 지구 외의 다른 행성에서도 인류들이 살아갈 수 있는 미래가 오리라 믿었다. 그리고 그가 지구라는 세상에 발을 내려 놓은 지 23년이 지난 지금, 세계 최연소 ASNA 우주 비행

www.acmicpc.net


2. 코드

#include <iostream>
#include <cmath>

using namespace std;

typedef unsigned long long ll;

int main() {
    int int_case;
	ll x, y, res,distance, level;
    
	cin >> int_case;

	for (int i = 0; i < int_case; i++) {
		cin >> x >> y;
		distance = y - x;

		if (distance > 0 && distance <= 3) {
			res = distance;
		}
		else {
			level = (int)sqrt(distance);

			if (((level + 1) * (level + 1)) - (level+1) < distance && distance < ((level + 1) * (level + 1))) {
				res = 2 * level+1;
			}
			else if (distance == level * level ) {
				res = 2 * level -1;
			}
			else {
				res = 2 * level;
			}
		}

		cout << res << "\n";
	}
    return 0;
}

3. 결과

백준 입출력

 


 

4. 문제 풀이 방식

  •  가능한 경우의 수를 모두 계산하여 최소의 개수를 찾는 방법 -> 시간 부족으로 인한 실패
  •  재귀함수를 작성하여 위와 같은 방식을 구현 -> 구현 실패
  •  각 거리 별 결과를 직접 작성하여 패턴을 분석 -> 특정 경우에서 자리수가 증가하는 모습이 보여짐
  •  해당 패턴을 기반으로 코드를 작성하여 제출 -> 50%에서 틀림
  •  반례를 확인 -> 작성한 코드에선 문제에서 주어진 가장 큰 수 (2147483647)의 처리가 불가
  •  자료형을 int -> unsigned long long으로 변경
  •  거리가 제곱근의 제곱과 같은 경우 결과에 -1을 해주어야 함
    ex) 거리가 9인경우 제곱근은 3이고, 자리수도 3 (2 * 2 - 1 = 3)
  •  아래는 분석한 자료임

패턴 찾기

  

   

728x90
반응형
728x90
반응형

문제 1. 블랙잭 (브론즈 2)

#include<iostream>

using namespace std;

int main(){
	int n, m, sum, min, res = 0;
	cin >> n >> m;
	int* card = new int[n];
	bool is_flag;

	for (int i = 0; i < n; i++) {
		cin >> card[i];
	}
	
	sum = 0;
	min = m;
	is_flag = true;
	for (int i = 0; i < n - 1 && is_flag; i++) {
		for (int j = i + 1; j < n && is_flag; j++) {
			for (int k = j + 1; k < n && is_flag; k++) {
				sum = card[i] + card[j] + card[k];
                
				if (sum == m) is_flag = false;
				if (min > m - sum && m >= sum) {
					min = m - sum;
					res = sum;
				}
			}
		}
	}

	cout << res << endl;

    return 0;
}

 

문제 2. 분해합 (브론즈 2)

#include <iostream>
#include <string>
#include <cmath> 
#include <map> 

using namespace std;

int func_2231_create_decompose(int a) {
	int len, res = a;

	len = to_string(a).length();

	for (int i = len; a > 0; i--) {
		res += a / pow(10, i);
		a %= (int)pow(10, i);
	}

	return res;
}

int main() {
	int a, key;
	cin >> a;

	map<int, int> m;

	for (int i = 1; i < a; i++) {
		key = func_2231_create_decompose(i);
		
		if(!m[key])
			m[key] = i;
	}

	cout << m[a];
    return 0;
}

 

문제 3. 덩치 (실버 5)

/*
*  문제 내용 이해가 중요한 문제였음.
*  map을 사용해서 구현한 버전
*/

#include <iostream>
#include <map>

using namespace std;

int main() {
    int int_case;
	int cnt, grade;
	int* bulk;

	cin >> int_case;

	map<char, int *> m_input;
	
    // 입력
	for (int i = 0; i < int_case; i++) {
		bulk = new int[2];

		cin >> bulk[0] >> bulk[1];

		m_input['a' + i] = bulk;
	}

	// 등수 : 나보다 덩치가 큰 사람의 수 + 1
	for (int i = 0; i < int_case; i++) {
		cnt = 1;

		for (int j = 0; j < int_case; j++) {
			// 덩치 : 키도 크고, 몸무게도 무거운 사람 수
			if (m_input['a' + i][0] < m_input['a' + j][0] && m_input['a' + i][1] < m_input['a' + j][1]) {
				cnt++;
			}
		}

		// 등수 출력
		cout << cnt << " ";
	}

	for (int i = 0; i < int_case; i++) {
		delete m_input['a' + i];
	}
    
    return 0;
}

/*
*  문제 내용 이해가 중요한 문제였음.
*  2차원 Array를 사용해서 구현한 버전
*/
#include <iostream>

using namespace std;

int main() {
	int int_case, cnt;
	cin >> int_case;
	int** arr = new int*[int_case];
	int* bulk;

	for (int i = 0; i < int_case; i++) {
		bulk = new int[2];
		cin >> bulk[0] >> bulk[1];
		arr[i] = bulk;
	}

	for (int i = 0; i < int_case; i++) {
		cnt = 1;
		for (int j = 0; j < int_case; j++) {
			if (arr[i][0] < arr[j][0] && arr[i][1] < arr[j][1]) {
				cnt++;
			}
		}
		cout << cnt << " ";
	}
    return 0;
}

 

 

문제 4. 체스판 다시 칠하기 (실버 5)

#include <iostream>
#include <cstring>

using namespace std;

int func_1018_bitmask(char **_map) {
	int cnt_1 = 0, cnt_2 = 0;
	char filter_1[8][8] = {
		{0, 1, 0, 1, 0, 1, 0, 1},
		{1, 0, 1, 0, 1, 0, 1, 0},
		{0, 1, 0, 1, 0, 1, 0, 1},
		{1, 0, 1, 0, 1, 0, 1, 0},
		{0, 1, 0, 1, 0, 1, 0, 1},
		{1, 0, 1, 0, 1, 0, 1, 0},
		{0, 1, 0, 1, 0, 1, 0, 1},
		{1, 0, 1, 0, 1, 0, 1, 0}
	};
	char filter_2[8][8] = {
		{1, 0, 1, 0, 1, 0, 1, 0},
		{0, 1, 0, 1, 0, 1, 0, 1},
		{1, 0, 1, 0, 1, 0, 1, 0},
		{0, 1, 0, 1, 0, 1, 0, 1},
		{1, 0, 1, 0, 1, 0, 1, 0},
		{0, 1, 0, 1, 0, 1, 0, 1},
		{1, 0, 1, 0, 1, 0, 1, 0}, 
		{0, 1, 0, 1, 0, 1, 0, 1}
	};

	for (int i = 0; i < 8; i++) {
		for (int j = 0; j < 8; j++) {
			if ( !(_map[i][j]^filter_1[i][j]) ) {
				cnt_1++;
			}
			if (!(_map[i][j] ^ filter_2[i][j])) {
				cnt_2++;
			}
		}
	}

	if (cnt_1 >= cnt_2) return cnt_2;
	else return cnt_1;
}

int main() {
	int n, m;
	int min, cnt;
	string tmp;
	cin >> n >> m;

	char** tmp_map = new char* [8];
	for (int i = 0; i < 8; i++) {
		tmp_map[i] = new char[8];
	}
	char** bwmap = new char* [n];
	for (int i = 0; i < n; i++) {
		bwmap[i] = new char[m];
	}

	for (int i = 0; i < n; i++) {
		cin >> tmp;
		for (int j = 0; j < m; j++) {
			if (tmp[j] == 'B') {
				bwmap[i][j] = 1;
			}
			else {
				bwmap[i][j] = 0;
			}
		}
	}

	cnt = 0;
	min = 64;
    
	for (int i = 0; i <= n - 8; i++) {
		for (int j = 0; j <= m - 8; j++) {
            
			for (int a = i, aa = 0; a < i + 8; a++, aa++) {
				for (int b = j, bb = 0; b < j + 8; b++, bb++) {
					tmp_map[aa][bb] = bwmap[a][b];
				}
			}
            
			cnt = func_1018_bitmask(tmp_map);
			if (cnt < min) {
				min = cnt;
			}
		}
	}
    
	cout << min << "\n";
    
    return 0;
}

 

문제 5. 영화감독 숌 (실버 5)

#include <iostream>
#include <cstring>

using namespace std;

int main() {
	int n, cnt=0;
	string tmp;

	cin >> n;

	for (int i = 666; i < 2100000000; i++) {
		tmp = to_string(i);
		if (tmp.find("666") != string::npos) {
			cnt++;

			if (cnt > 10000) break;
			if (cnt == n) {
				cout << tmp << "\n";
			}
		}
	}
}

 

결과

 

728x90
반응형
728x90
반응형

1. 문제

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

 

15965번: K번째 소수

자연수 K가 주어진다.(1 ≤ K ≤ 500,000)

www.acmicpc.net


2. 코드

#include <iostream>
#include <cstring>

using namespace std;

bool *Sieve_of_Eratosthenes(int m) {
    bool* arr = new bool[m + 1];

    memset(arr, 1, sizeof(bool) * (m+1));
    arr[0] = false;
    arr[0] = false;

    for (int i = 2; i < m + 1; i++) {
        if (arr[i] == true) {
            for (int j = i * 2; j < m + 1; j += i) {
                arr[j] = false;
            }
        }
    }

    return arr;
}


int main() {
    int a, max = 50000000, sum=0;
    bool* arr = Sieve_of_Eratosthenes(max);
    cin >> a;

    for (int i = 0; i <= max; i++) {
        sum += arr[i];
        
        if (sum == a+1) {
            cout << i << endl;
            break;
        }
    }
    
    return 0;
}

3. 결과


4. 리뷰

  • 에라토스테네스의 채 알고리즘을 사용하여 충분히 큰 소수 범위의 소수 여부 배열을 생성함.
  • 해당 여부가 1인 경우(소수인 경우)를 누적하여 원하는 위치의 소수를 찾음
  • 100점 통과는 가능했지만 좀 더 효율적인 방법이 필요함.
728x90
반응형

+ Recent posts