Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[투 포인터] 2076278 윤지윤 #316

Open
wants to merge 6 commits into
base: 2076278-윤지윤
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions 10_이분 탐색/도전/2343.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

using namespace std;

int cntBlu(int time, vector<int> &lecture){
int blu =0; //블루레이 갯수
int sum = lecture[0]; // 한 블루레이에 저장되는 영상의 길이 합
for(int i=1;i<lecture.size();i++){
if((sum+lecture[i])<=time){ //다음 영상을 합쳤을 때 길이와 time(블루레이의 길이) 비교
sum+= lecture[i];
}else{
blu++; //합이 더 길다면 블루레이 갯수 +1
sum= lecture[i]; // 한 블루레이에 저장되는 영상의 길이도 i번째 영상으로 초기화
}
}
return blu;
}

int binarySearch(int left,int right,int target, vector<int> &lecture){
while(left<=right){
int mid = (left+right)/2;
int cnt = cntBlu(mid,lecture);
if(cnt >=target){ //블루레이의 갯수가 target보다 많다면 힌 블루레이의 크기를 늘려줌
left = mid +1;
}else{
right = mid - 1;
}
}
return left;

}

int main(){
cin.tie(0);
cout.tie(0);
ios_base::sync_with_stdio(NULL);
int n,m;
cin >> n >>m;
vector<int> lecture(n,0);
for(int i=0;i<n;i++){
cin >>lecture[i];
}

int sum = accumulate(lecture.begin(),lecture.end(),0);

//최소는 영상의 최댓값, 최대는 영상의 전체 합
cout << binarySearch(*max_element(lecture.begin(),lecture.end()),sum,m,lecture);

}
41 changes: 41 additions & 0 deletions 10_이분 탐색/필수/10815.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


int binarySearch(int left, int right, int key,vector<int>& card){
while(left<=right){
int mid =(left+right)/2;
if(card[mid] ==key){
return 1;
}
else if(card[mid]>key){
right = mid -1;
}else{
left = mid+1;
}
}
return 0;
}

int main(){
cin.tie(0);
cout.tie(0);
ios_base::sync_with_stdio(NULL);
int n,m,key;
cin >>n;
vector <int> card (n,0);
for(int i=0;i<n;i++){
cin >>card[i];
}
sort(card.begin(),card.end());

cin >>m;
while(m--){
cin >>key;
cout <<binarySearch(0,n-1,key,card)<<" ";
}

}
85 changes: 85 additions & 0 deletions 10_이분 탐색/필수/14500.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include<iostream>
#include<vector>
#include <algorithm>

using namespace std;

vector<vector<int>>board;

int ans;

void dfs(int x, int y, int depth, int sum) {

vector<int> dx = { -1,0,1,0 }; //좌상우하, x축 방향으로의 움직임
vector<int> dy = { 0,1,0,-1 }; // y축 방향으로의 움직임

if (depth == 4) { // 칸 4개 선택했으면 ans 최대값 갱신
ans = max(ans, sum);
return;
}

// 아래 코드가 들어가면 가지치기가 돼 백트래킹이 돼요!
//if (ans >= MAX * (4 - cnt) + sum) {
// return;
//}

for (int i = 0; i < 4; i++) {
// 선택할 칸
int nx = x + dx[i]; //i가 0 이라면 x=x-1 y=y, i가 2 라면 x=x+1 y=y,
int ny = y + dy[i]; //i가 1이라면 x=x y=y+1, i가 4 라면 x=x y=y-1

if (nx < 0 || nx >= board.size() || ny < 0 || ny >= board[0].size() || !board[nx][ny]) { // 범위를 벗어났거나 이미 방문한 블록이라면 넘어가기
continue;
}

int temp = board[nx][ny]; // 방문 처리하기 전 해당 칸 가치 저장
board[nx][ny] = 0; // 방문 처리 : 4개를 선택함에 있어서 똑같은 블록을 선택하지 않기 위해

// 다음 탐색 -> depth 1 증가 && sum값에 현재 칸 가치 더하기
if (depth == 2) { // ㅜ 모양은 현재 위치에서 다시 탐색!
dfs(x, y, depth + 1, sum + temp);
}
dfs(nx, ny, depth + 1, sum + temp); // 선택한 칸으로 이동

board[nx][ny] = temp; // 이후의 케이스에서 재방문할 수 있으므로 원래대로 돌려줌

}
}

/*
* HINT : 하나의 도형은 무언가 특별한 것 같아요! or 테트로미노의 모양은 탐색의 관점에서 특징이 있는 것 같아요!
* 1. ㅜ 모양을 제외한 테트로미노의 모양은 깊이가 4인 dfs의 탐색 모양
* -> dfs로 블록을 하나씩 선택해가면서 개수(cnt)와 합(sum)을 계산
* -> 4개 선택하면 최댓값 갱신
* 2. 예외 : ㅜ 모양은 블록을 2개 선택했을 때 현재 블록에서 다시 블록을 선택해준다.
*/


int main() {

// 입력
int n, m; //세로 n, 가로 m
cin >> n >> m;
board.assign(n, vector<int>(m, 0)); //테트로미노를 놓을 종이


for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> board[i][j]; //각 칸에 쓰여진 수 입력받기
}
}

// 연산
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int temp = board[i][j];
board[i][j] = 0; //i,j 번째칸 방문했으므로 0 처리
dfs(i, j, 1, temp);
board[i][j] = temp; //다시 방문할 수 있으므로 원래대로 되돌려놓음
}
}

// 출력
cout << ans;
return 0;
}
45 changes: 45 additions & 0 deletions 10_이분 탐색/필수/16401.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int lenSnack(int length,vector<int> &l){
int cnt =0;
for(int i=0;i<l.size();i++){
if(l[i]>=length){
cnt+=l[i]/length; //한 개의 과자에서 여러 조각이 나올 수 있음. (과자의 길이 / 조각의 길이)
}
}
return cnt;
}

int binarySearch(int left, int right, int target, vector<int>& l){
while(left<=right){
int mid =(left+right)/2;
int num = lenSnack(mid,l);
if(num >=target){ //나눠진 과자의 갯수가 target보다 크다면 조각의 길이를 더 길게해 갯수를 줄일 수 있도록 함
left = mid +1;
}
else{
right = mid -1;
}
}
return left-1;
}

int main(){
int m,n;
cin >>m >> n;
vector <int> l (n,0);
for(int i=0; i<n;i++){
cin >>l[i];
}

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

//조각의 최소 길이는 1 최대 길이는 l[n-1]
cout <<binarySearch(1,l[n-1],m,l);
return 0;

}
74 changes: 74 additions & 0 deletions 11_투 포인터/필수/14503.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <iostream>

using namespace std;

const int SIZE = 50; //방 최대 크기
const int CLEAN = 2; //청소상태는 2
int n, m, cnt = 0; // 세로 크기, 가로 크기, 청소한 칸 개수

int board[SIZE][SIZE]; // (0: 빈 칸, 1: 벽, 2: 청소 완료)
int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0}; // 북 동 남 서

void dfs(int row, int col, int dir) {
// 1. 현재 위치 청소
if(board[row][col] != CLEAN) { //현재 위치한 청소 되지 않았다면
cnt++; //청소한 칸 +1
}
board[row][col] = CLEAN; //해당 위치 청소 표시

// [현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는가]
// 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우
for(int i = 0; i < 4; i++) { // 3-1. 반시계 방향으로 90º 회전
int new_dir = (dir-i+3) % 4;
int new_row = row + dy[new_dir], new_col = col + dx[new_dir]; //반시계 방향으로 회전한 후 전진했을 때 좌표

if(board[new_row][new_col] == 0) { // 3-2. 아직 청소되지 않은 빈 칸 발견
dfs(new_row, new_col, new_dir); // 한 칸 전진
return;
}
}

// 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우
int back_dir = (dir+2) % 4;
int back_row = row + dy[back_dir], back_col = col + dx[back_dir]; //한 칸 후진했을 때 위치

// [바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가]
// 2-2. 뒤쪽 칸이 벽이라 후진할 수 없는 경우
if(board[back_row][back_col] == 1) {
return; //동작 멈춤
}
// 2-1. 바라보는 방향을 유지한 채로 한 칸 후진
dfs(back_row, back_col, dir); // 방향 유지한 상태로 후진 (2-3)
return;
}

/*
* [로봇 청소기 작동]
* 1. 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
* 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우,
* 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
* 2-2. 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
* 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우,
* 3-1. 반시계 방향으로 90º 회전한다.
* 3-2. 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.
* 3-3. 1번으로 돌아간다.
*/

int main() {
int r, c, d; // 로봇 청소기 정보

// 입력
cin >> n >> m; //방의 크기
cin >> r >> c >> d; //로봇 청소기 초기 위치, 바라보는 방향

for(int i = 0; i < n; i++) { //칸 상태 입력
for(int j = 0; j < m; j++) {
cin >> board[i][j];
}
}

// 연산 & 출력
dfs(r, c, d);
cout << cnt;
return 0;
}
55 changes: 55 additions & 0 deletions 11_투 포인터/필수/20437.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

typedef pair<int,int> ci;


ci containK(int k, string w, vector<int> &al){
int len,max_len=-1,min_len=10001;

for (int i =0;i<w.length();i++){
if(al[w[i]-'a']<k){
continue;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 if문을 통과하는 경우 continue를 만나게 되므로 아래 코드를 실행하지 않게 되죠! 아래 else문은 인덴테이션이 많아질 경우 작성하지 않으셔도 괜찮을 것 같네요😀

}else{
int cnt =0;
for(int j =i;j<w.length();j++){

if(w[i]==w[j]){
cnt ++;
if(cnt == k){
len = j-i+1;
max_len =max(len,max_len);
min_len = min(len,min_len);
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인덴테이션이 많아지고 있네요! 3중 이상의 인덴테이션이 생기면 이 중괄호가 어디에 속한 중괄호인지 알아보기 어려워질 때가 있죠😥 if(w[i] != w[j]) { continue; }를 사용해 인덴테이션을 하나 제거해보면 어떨까요?


}

}
}
return {min_len,max_len};
}

int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int T,k;
string w;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

변수명의 표기법은 통일해서 사용해주세요! 참고로 저희 튜터링에서는 변수명은 스네이크 표기법을, 상수명은 대문자로 표기할 것을 권장해드리고 있습니다😊

cin >> T;
while(T--){
vector<int> al (26,0);
cin >>w >> k;
for (int i =0;i<w.length();i++){
al[w[i]-'a']++;
}
ci ans=containK(k,w,al);
if(ans.second ==-1 || ans.first ==10001){
cout <<-1;
}else{
cout <<ans.first<<" "<<ans.second;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main 깔끔하고 좋습니다!!😍

Copy link

@kwakrhkr59 kwakrhkr59 May 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

출력 형식만 한번 확인해주세요...! 이 부분이 놓치기 쉬운 부분이죠😂 딱 하나만 수정해주시면 코드는 잘 돌아갈 것 같네요! 다만 위에서 이중 for문을 돌면서 시간 초과가 날 것 같네요😥 cnt가 k보다 커지면 탐색할 의미가 없어지니 cnt==k가 되면 탐색을 중지시켜보면 어떨까요? 한번 시도해보시고 그래도 어려우시다면 다시 한 번 질문해주세요😁

}
}
Loading