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

[동적계획법] 10월 3일 #8

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
49 changes: 49 additions & 0 deletions 09월 27일 - 동적계획법/11048.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <iostream>
#include <vector>

using namespace std;

int n, m;
vector<vector<int>> board(n, vector<int>(m, 0));
vector<vector<int>> dp;
Comment on lines +6 to +8
Copy link

Choose a reason for hiding this comment

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

전역 변수 사용은 지양해주세요! 이 문제는 지역 변수로 충분히 해결 가능합니다!


void calc()
{
dp[0][0] = board[0][0];

for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i > 0 && j > 0)
{
dp[i][j] = max(max(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + board[i][j];
}
else if (i > 0)
{
dp[i][j] = dp[i - 1][j] + board[i][j];
}
else if (j > 0)
{
dp[i][j] = dp[i][j - 1] + board[i][j];
}
Comment on lines +18 to +29
Copy link

Choose a reason for hiding this comment

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

더미 인덱스(가장 앞줄이 0으로 채워진 vector)를 사용하면 이 부분을 한번에 처리할 수 있습니다!

}
}
}

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

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

calc();

cout << dp[n - 1][m - 1];
}
40 changes: 40 additions & 0 deletions 09월 27일 - 동적계획법/11053.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int maxElement(int n, vector<int> &nums)
{
vector<int> dp(n, 1);

for (int i = 1; i < n; i++)
{
int max_e = 0;
for (int j = 0; j < i; j++)
{
if (nums[j] < nums[i] && dp[j] > max_e)
{
max_e = dp[j];
}
}
dp[i] += max_e;

Choose a reason for hiding this comment

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

흠 사실.. 정답 유무와는 크게 관계없는 부분이지만 += 보다는 = 로 쓰는게 의도를 더 잘 드러낼 수 있을 것 같아용! ㅎㅎ

Choose a reason for hiding this comment

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

p2. i번째 루프에서 이전 원소 ( 0 ~ i-1) 들로 끝나는 최장 수열의 길이 중 최댓값을 저장하기 위해서 max_e 변수를 사용해주셨는데요! max_e를 없애고 바로 dp[i]에 최댓값을 갱신하는 식으로 작성하면 코드가 조금 더 간결해질 것 같아요 :)
그러나 사실 짧다고 다 좋은 코드는 아니니,, 취향껏 받아들여주시면 될 것 같습니다😊😊

}

return *max_element(dp.begin(), dp.end());
}

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

vector<int> nums(n);

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

cout << maxElement(n, nums);
}
117 changes: 117 additions & 0 deletions 09월 27일 - 동적계획법/20055.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include <iostream> //입출력 라이브러리
#include <deque> //deque 자료구조 사용

using namespace std;

/**
* [힌트] 벨트의 회전과 로봇의 이동을 인덱스로 관리해볼까요?
* 1단계(rotate()): 벨트 회전 + n번째 칸 로봇 내리기
* 2단계(move()) : 로봇 이동시키기 + n번째 칸 로봇 내리기
* 3단계(put()) : 1번째 칸에 로봇 올리기
*/

struct info
{
int power; //벨트의 내구도
int robot; //벨트 위 로봇 존재 여부(1: 존재o, 0:존재x)
};

/**1단계*/
void rotate(deque<info> &belt, int n)
{
//벨트 회전
belt.push_front(belt.back()); //맨 뒤에 있던 로봇을 맨 앞에 푸쉬
belt.pop_back(); //맨 뒤에 있던 로봇 삭제

//n번째 칸 로봇 내리기
if (belt[n - 1].robot)
{ //n번째 칸에 로봇이 있다면
belt[n - 1].robot--; //로봇 내리기
}
}

/**2단계*/
void move(deque<info> &belt, int n)
{ //로봇 이동시키기
/*
* [로봇 이동을 위한 조건]
* 1. 현재 칸에 로봇이 존재하고(belt[i].robot)
* 2. 다음 칸에 로봇이 존재하지 않고(!belt[i+1].robot)
* 3. 다음 칸의 내구도가 1 이상일 때(belt[i].power)
*
* 이때 가장 먼저 올라간 로봇은 가장 뒤에 존재! -> 뒤에서부터 접근하기
*/

int cur = 2 * n - 1, next; //cur:현재 칸, next: 다음 칸
while (cur >= 0)
{ //먼저 올라간 로봇부터 옮기기 시작
next = (cur + 1) % (2 * n); //다음 칸 인덱스 설정
if (belt[cur].robot && !belt[next].robot && belt[next].power)
{ //로봇을 이동시킬 수 있는 경우
belt[cur].robot--; //현재 칸에서 로봇을 옮겨서
belt[next].robot++; //다음 칸으로 로봇을 이동시킴
belt[next].power--; //로봇을 이동시킴에 따라 내구도 감소
}

cur--; //그 다음에 올라간 로봇에 대해 다시 시행
}

//n번째 칸 로봇 내리기
if (belt[n - 1].robot)
{ //로봇이 있다면
belt[n - 1].robot--; //로봇을 내림
}
}

/**3단계*/
void put(deque<info> &belt)
{
//첫 번째 칸에 로봇 올리기
if (belt[0].power)
{ //첫 번째 칸에 내구도가 1 이상이라면
belt[0].robot++; //첫 번째 칸에 로봇을 올리고
belt[0].power--; //로봇을 올림에 따라 내구도 감소
}
}

int countZero(deque<info> &belt, int n)
{ //벨트에서 내구도가 0인 칸 세기
int cnt = 0; //내구도가 0인 칸을 셀 변수
for (int i = 0; i < 2 * n; i++)
{ //모든 칸에 대해 시행
if (belt[i].power == 0)
{ //해당 칸의 내구도가 0이라면
cnt++; //개수 증가
}
}

return cnt; //결과값 반환
}

int main()
{
//cin, cout 속도를 향상시키기 위하여 사용
ios_base::sync_with_stdio(0);
cin.tie(0);

//n과 k 입력받기
int n, k;
cin >> n >> k;
deque<info> belt(2 * n, {0, 0}); //벨트 초기화

for (int i = 0; i < 2 * n; i++)
{
cin >> belt[i].power; //벨트 내구도 입력받기
}

int stage = 0; //현재 진행 중인 단계
do
{
rotate(belt, n); //벨트 회전
move(belt, n); //로봇 이동
put(belt); //로봇 올리기
stage++; //단계 증가
} while (countZero(belt, n) < k); //내구도가 0인 칸이 k개 미만일 동안 시행

cout << stage; //몇 번째 단계인지 출력
}
71 changes: 71 additions & 0 deletions 09월 27일 - 동적계획법/20923.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//참고한 블로그 링크 : https://seastar105.tistory.com/75
//deque 배열의 인덱스를 이용해 코드를 효율적으로 간소화시킨 아이디어를 참고
Comment on lines +1 to +2
Copy link

@Dong-droid Dong-droid Oct 3, 2022

Choose a reason for hiding this comment

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

👍. 어디를 참고했다고 알려주시는 거 너무 좋습니다~ 🥇

#include <iostream>
#include <deque>

using namespace std;

deque<int> deck[2], ground[2];

Comment on lines +7 to +9

Choose a reason for hiding this comment

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

P3. 클린 코드를 위해서 전역 변수 사용을 지양하시기를 부탁드립니다!! 😄

int check()
{
//도도가 종을 칠 수 있는 경우
if (ground[0].size() && ground[0].back() == 5)
return 0;
Comment on lines +12 to +14

Choose a reason for hiding this comment

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

P3. 클린 코드를 위해서 중괄호를 사용해주시기를 부탁드립니다!! 🎃

if (ground[1].size() && ground[1].back() == 5)
return 0;

//수연이가 종을 칠 수 있는 경우
if (ground[0].size() && ground[1].size() && ground[0].back() + ground[1].back() == 5)
return 1;

//그외
return -1;
}

int main()
{
int n, m, x, y;
cin >> n >> m;

while (n--)
{
cin >> x >> y;
deck[0].push_front(x);
deck[1].push_front(y);
}

int turn = 0;

while (m--)
{
Comment on lines +39 to +41
Copy link

@Dong-droid Dong-droid Oct 3, 2022

Choose a reason for hiding this comment

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

P3. 여기 while문부터는 함수화를 해주시면 👍 코드가 될 것 같습니다!

ground[turn].push_back(deck[turn].front());
deck[turn].pop_front();

//게임 진행 도중 deck의 카드 수가 0개가 되는 경우
if (deck[turn].empty())
{
break;
}

//종을 칠 수 있는 사람을 확인
int w = check();

//종을 쳤다면 카드 더미를 합친다
if (w != -1)
{
deck[w].insert(deck[w].end(), ground[1 - w].begin(), ground[1 - w].end());
deck[w].insert(deck[w].end(), ground[w].begin(), ground[w].end());
ground[1 - w].clear();
ground[w].clear();
}

turn = 1 - turn;
Comment on lines +57 to +63

Choose a reason for hiding this comment

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

P3. 1-w 도 좋지만 저희에게는 !이 있죠!!!!
!turn !w 이렇게요~ 😀

}

//이긴 사람 체크
if (deck[0].size() >= deck[1].size())
cout << "do";
if (deck[0].size() <= deck[1].size())
cout << "su";
}
34 changes: 34 additions & 0 deletions 09월 27일 - 동적계획법/2156.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <iostream>
#include <vector>

using namespace std;

int calc(int n, vector<int> &inputs)
{
vector<int> dp(n + 1, 0);

dp[1] = inputs[1];
dp[2] = inputs[1] + inputs[2];

for (int i = 3; i <= n; i++)
{
dp[i] = max(max(dp[i - 2] + inputs[i], dp[i - 1]),dp[i-3]+inputs[i-1]+inputs[i]);
}

return dp[n];
}

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

vector<int> inputs(n + 1);

for (int i = 1; i <= n; i++)
{
cin >> inputs[i];
}

cout << calc(n, inputs);
}