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

Review2 #9

Open
wants to merge 6 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
44 changes: 44 additions & 0 deletions 9월 28일 - 동적 계획법/10844.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <iostream>
#include <vector>

using namespace std;

#define DIV 1000000000;

int main()
{
int n, ans = 0;
cin >> n;
vector<vector<int>> dp(100, vector<int>(10,0));
// 한 자리 수
for (int i = 0; i < 10; i++)
dp[0][i] = 1;
Comment on lines +13 to +15
Copy link

Choose a reason for hiding this comment

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

p2. 문제에서 0으로 시작하는 수는 없다고 했었죠..!

// i: 자리의 수, j: 일의 자리 수
for (int i = 1; i < n; i++)
{
for (int j = 0; j < 10; j++)
{
if (j == 0) // 일의 자리 수가 0
dp[i][0] = dp[i - 1][1];
else if (j == 9) // 일의 자리 수가 9
dp[i][9] = dp[i - 1][8];
else // 일의 자리 수가 1~8
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j + 1];
dp[i][j] = dp[i][j] % DIV;
}
}
/*
for (int a = 0; a < n; a++)
{
for (int b = 0; b < 10; b++)
cout << dp[a][b] << ' ';
cout << '\n';
}
cout << '\n';
*/
// 0으로 시작하는 것 제외
for (int i = 1; i < 10; i++)
ans = (ans + dp[n-1][i]) % DIV;
Comment on lines +39 to +41
Copy link

Choose a reason for hiding this comment

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

p2. 주석 써주신 것에 의하면 dp[n-1][i]는 n자릿수 중 i로 '끝나는' 쉬운 계단 수의 개수를 저장하고 있어요!
현재 초기화를 해주실 때 dp[0][0]값을 1로 해주셔서 지금 로직은 i로 '시작하는' 쉬운 계단 수를 구하고 있었던 것 같아요. 그래서 답을 구하실 때도 0번 열을 제외하셔야 했던 거구요!

i로 끝나는 쉬운 계단 수를 구하기 위해선 초기화를 어떻게 해야 할까요!?

cout << ans <<'\n';
return 0;
}
26 changes: 26 additions & 0 deletions 9월 28일 - 동적 계획법/15486.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 14501 보다 N의 범위가 크다 (1500000)
int main()
{
int n;
cin >> n;
vector<pair<int, int>> v;
v.assign(n, {});
// 입력
for (int i = 0; i < n; i++)
cin >> v[i].first >> v[i].second;
vector<int> dp(1500001, 0);
for(int i=0; i<n; i++)
{
// 상담 한다
dp[i + v[i].first] = max(dp[i + v[i].first], dp[i] + v[i].second);
Copy link

Choose a reason for hiding this comment

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

p2. 백준 제출 시 문제가 되지는 않지만, v[i].first를 더해줌으로써 dp의 최대 범위를 넘어갈 수 있으므로 인덱스 접근이 가능한지 조건문으로 먼저 체크를 해주는 게 좋아요!!

// 상담 안 한다
dp[i + 1] = max(dp[i + 1], dp[i]);
}
cout << dp[n] << '\n';
}
75 changes: 75 additions & 0 deletions 9월 28일 - 동적 계획법/20923.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <iostream>
#include <deque>

using namespace std;

deque<int> d[2], g[2];
int turn = 0;

void round()
{
// SUYEON
if (!g[0].empty() && !g[1].empty() && (g[0].front() + g[1].front() == 5))
{
while (!g[0].empty())
{
d[1].push_back(g[0].back());
g[0].pop_back();
}
while (!g[1].empty())
{
d[1].push_back(g[1].back());
g[1].pop_back();
}
Comment on lines +14 to +23
Copy link

Choose a reason for hiding this comment

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

p2. 겹치는 부분이 있네요! 현재 누구의 덱에 저장하는 지와 어느 그라운드에서 가져오는 지를 보내주면 함수화할 수 있을 것 같아요!!

}
// DODO
else if ((!g[0].empty() && g[0].front() == 5) || (!g[1].empty() && g[1].front() == 5))
{
while (!g[1].empty())
{
d[0].push_back(g[1].back());
g[1].pop_back();
}
while (!g[0].empty())
{
d[0].push_back(g[0].back());
g[0].pop_back();
}
}
}

string win()
{
if (d[0].size() > d[1].size())
return "do";
else if (d[0].size() < d[1].size())
return "su";
return "dosu";
}

string game(int m)
{
while (m--)
{
g[turn].push_front(d[turn].front());
d[turn].pop_front();
if (d[turn].empty())
break;
round();
turn = (turn == 1) ? 0 : 1;
Copy link

Choose a reason for hiding this comment

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

p2. turn은 0 또는 1로만 이루어지네요! 그럼 무슨 자료형으로 사용하는 게 더 좋을까요? 그리고 상태가 2개 뿐이니 삼항연산자를 쓰지 않고도 턴을 바꿔줄 수 있어요!

}
return win();
}

int main()
{
int n, m, input1, input2;
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> input1 >> input2;
d[0].push_front(input1);
d[1].push_front(input2);
}
cout << game(m)<<'\n';
}
29 changes: 29 additions & 0 deletions 9월 28일 - 동적 계획법/2294.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
int n, k, input;
cin >> n >> k;
vector<int> coin(100, 0);
// 동전의 최대 가치 100000만큼 dp 생성
// 최솟값을 구해야 하므로 10001(k의 최대값보다 큰 값)로 초기화
vector<int> dp(100001, 10001);
Comment on lines +11 to +14
Copy link

Choose a reason for hiding this comment

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

p3. 지금 n, k를 모두 알고 있는 상태니 벡터 크기는 n, k에 맞게 선언해 줘도 좋아요!

dp[0] = 0;
// 코인 값 입력
for (int i = 0; i < n; i++)
cin >> coin[i];
// 최솟값 구하기
for (int i = 0; i < n; i++)
for (int j = coin[i]; j <= k; j++)
dp[j] = min(dp[j], dp[j - coin [i]] + 1);
Comment on lines +20 to +22
Copy link

Choose a reason for hiding this comment

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

👍👍👍

// 불가능한 경우 -1 출력
if (dp[k] == 10001)
cout << -1 << '\n';
else
cout << dp[k] << '\n';
return 0;
}
89 changes: 89 additions & 0 deletions 9월 28일 - 동적 계획법/3190.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <iostream>
#include <vector>

using namespace std;

int n, l;
vector<pair<int, char>> d(l, { 0, ' ' });
// 오른쪽: 0 아래: 1 왼쪽: 2 위: 3
vector<pair<int, int>> move_dir = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };

bool inRange(int a, int b)
{
if (a < 0 || a >= n || b < 0 || b >= n)
return false;
return true;
}

int dummy(vector<vector<int>> board)
{
int cnt = 0, d_cnt = 0, curr_dir = 0, apple = 0;
char turn_d = ' ';
int tail_length = 1, head_length = 1, r_tail = 0, c_tail = 0, r_head = 0, c_head = 0;
board[0][0] = 1;
while (true)
{
// 시간 증가
cnt++;
// 뱀 머리 이동
if (!inRange(r_head + move_dir[curr_dir].first, c_head + move_dir[curr_dir].second) || board[r_head + move_dir[curr_dir].first][c_head + move_dir[curr_dir].second] > 0)
return cnt;
else
{
r_head += move_dir[curr_dir].first;
c_head += move_dir[curr_dir].second;
apple = board[r_head][c_head] == -1 ? 1 : 0;
board[r_head][c_head] = ++head_length;
}
if (apple == 0) // 사과를 못 먹은 경우 몸 길이 유지
{
board[r_tail][c_tail] = 0;
tail_length++;
for (int i = 0; i < 4; i++)
{
if (inRange(r_tail + move_dir[i].first, c_tail + move_dir[i].second) && board[r_tail + move_dir[i].first][c_tail + move_dir[i].second] == tail_length)
{
r_tail += move_dir[i].first;
c_tail += move_dir[i].second;
break;
}
}
Comment on lines +42 to +50
Copy link

Choose a reason for hiding this comment

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

p1. 지금 꼬리를 자르고, 그 전의 꼬리를 찾기 위한 연산이 다소 복잡하게 이루어지고 있어요! 그 전의 꼬리의 위치를 다른 컨테이너에 계속 저장하면서 왔다면 어떨까요? 즉, 뱀의 위치들을 저장하는 컨테이너를 따로 관리하는 거죠. 그리고 그 컨테이너는 삽입과 삭제가 자유롭게 이루어질 수 있는 거면 좋을 것 같아요! 컨테이너를 활용하면 꼬리의 삭제가 훨씬 간편해질 거에요!

}
// 뱀의 방향 변환 정보
if (d_cnt < l)
{
if (d[d_cnt].first == cnt)
{
turn_d = d[d_cnt].second;
d_cnt++;
if (turn_d == 'L')
curr_dir = curr_dir == 0 ? 3 : curr_dir - 1;
else if (turn_d == 'D')
curr_dir = curr_dir == 3 ? 0 : curr_dir + 1;
}
}
}
}

int main()
{
int k;
cin >> n >> k;
vector<vector<int>> board(n, vector<int>(n, 0));
int row, col, x;
char c;
// 사과
for (int i = 0; i < k; i++)
{
cin >> row >> col;
board[row-1][col-1] = -1;
}
// 방향
cin >> l;
for (int i = 0; i < l; i++)
{
cin >> x >> c;
d.push_back(make_pair(x, c));
}
cout << dummy(board) << '\n';
}