ê¸ˆê³ ¶
바로 코드 짜면 ì €ë²ˆì²˜ëŸ¼ ë§�해버릴 것만 같아서, ì �í™”ì‹� ë§Œë“¤ê³ , 간단히 ì¦�명까지 í•˜ê³ ì½”ë“œë¥¼ 짰다. 층수 n, ê¸ˆê³ ìˆ˜ k ë�¼ í• ë•Œ, 현재 복잡ë�„ O(nk). 구간 ê°’ì�„ ì €ìž¥í•œë‹¤ë©´ 메모리와 시간 모ë‘� ë�” 줄ì�¼ìˆ˜ 있ì�„ 것ì�´ë‹¤.
í’€ì�´ ¶
T(n, k) 를 층수 n ê³¼ ê¸ˆê³ ìˆ˜ k ì�¼ë•Œì�˜ í•´ë�¼ 하ìž�. 여기서 n ì�„ k ê°œì�˜ ê¸ˆê³ ë¥¼ ê°€ì§€ê³ , T(n, k) 횟수 ë§Œì—� 모ë‘� 테스트 í• ìˆ˜ 있는 건물ì�˜ 최대높ì�´ë�¼ 하ìž�.
층수가 n ì�¸ 건물중 해를 찾는 위치ì—� 첫 ê¸ˆê³ ë¥¼ ë–¨ì–´ëœ¨ë¦°ë‹¤ê³ í•˜ìž�. 그러면 건물ì�€ ê·¸ 위치 아래와 위로 나뉘어지며, 위쪽ì�€ T(b, k) ê°€ ë�˜ê³ , 아래쪽ì�€ T(a, k-1)ì�´ ë�œë‹¤. 여기서 a, b는 첫 ê¸ˆê³ ë¥¼ 떨어뜨린 위치를 기준으로 나뉘어진 위 아래 건물ì�˜ 층수다. 여기서 ë¬¸ì œì�˜ ì •ì�˜ì—� ë”°ë�¼ 우리가 êµ¬í•˜ê³ ìž� 하는 해는
{{| max{ T(b, k), T(a, k-1) } + 1 |}} �다.
그런ë�° 여기서 T(b,k) > T(a, k-1) ì�´ê±°ë‚˜ T(b,k) < T(a,k-1) ì�´ë�¼ë©´ n = a + b + 1 ì�¸ 건물ì�˜ 층수가 우리가 처ì�Œì—� ê°€ì •í•œ nì�´ T(n,k) 횟수만ì—� 테스트 í• ìˆ˜ 있는 건물ì�˜ 최대 높ì�´ë�¼ëŠ” ê°€ì •ê³¼ 모순ë�œë‹¤. ë”°ë�¼ì„œ T(b,k) = T(a,k-1) ì�´ë‹¤. ë”°ë�¼ì„œ
{{| T(a+b+1, k) = T(b,k) + 1 = T(a,k-1) + 1 |}} ì�´ë‹¤. 여기서 a 와 b ë˜�한 건물ì�˜ 최대 높ì�´ìž„ì�„ 만족해야 한다. 초기값 T(1, k) = 1, T(n, 1) = n ì�„ ì�´ìš©í•˜ì—¬ ê°’ì�„ êµ¬í• ìˆ˜ 있다.
층수가 n ì�¸ 건물중 해를 찾는 위치ì—� 첫 ê¸ˆê³ ë¥¼ ë–¨ì–´ëœ¨ë¦°ë‹¤ê³ í•˜ìž�. 그러면 건물ì�€ ê·¸ 위치 아래와 위로 나뉘어지며, 위쪽ì�€ T(b, k) ê°€ ë�˜ê³ , 아래쪽ì�€ T(a, k-1)ì�´ ë�œë‹¤. 여기서 a, b는 첫 ê¸ˆê³ ë¥¼ 떨어뜨린 위치를 기준으로 나뉘어진 위 아래 건물ì�˜ 층수다. 여기서 ë¬¸ì œì�˜ ì •ì�˜ì—� ë”°ë�¼ 우리가 êµ¬í•˜ê³ ìž� 하는 해는
{{| max{ T(b, k), T(a, k-1) } + 1 |}} �다.
그런ë�° 여기서 T(b,k) > T(a, k-1) ì�´ê±°ë‚˜ T(b,k) < T(a,k-1) ì�´ë�¼ë©´ n = a + b + 1 ì�¸ 건물ì�˜ 층수가 우리가 처ì�Œì—� ê°€ì •í•œ nì�´ T(n,k) 횟수만ì—� 테스트 í• ìˆ˜ 있는 건물ì�˜ 최대 높ì�´ë�¼ëŠ” ê°€ì •ê³¼ 모순ë�œë‹¤. ë”°ë�¼ì„œ T(b,k) = T(a,k-1) ì�´ë‹¤. ë”°ë�¼ì„œ
{{| T(a+b+1, k) = T(b,k) + 1 = T(a,k-1) + 1 |}} ì�´ë‹¤. 여기서 a 와 b ë˜�한 건물ì�˜ 최대 높ì�´ìž„ì�„ 만족해야 한다. 초기값 T(1, k) = 1, T(n, 1) = n ì�„ ì�´ìš©í•˜ì—¬ ê°’ì�„ êµ¬í• ìˆ˜ 있다.
코드 ¶
~cpp
// Safe
#include <iostream>
using namespace std;
#define MAXN 500
static int d[MAXN+1][MAXN+1];
static int n, k;
void init_table()
{
for (int i = 1; i <= MAXN; i++)
{
d[1][i] = 1;
d[i][1] = i;
}
}
int find_max_n(int k, int value)
{
for (int i = 1; i <= MAXN; i++)
if (value < d[i][k])
return i - 1;
return -1;
}
void fill_cell(int k)
{
int a, b, t, value;
t = value = 1;
while (t < MAXN)
{
b = t;
a = find_max_n(k - 1, value);
t = a + b + 1;
for (int i = b + 1; i <= __min(t,MAXN); i++)
d[i][k] = value + 1;
value++;
}
}
void set_dynamic_table()
{
init_table();
for (int k = 2; k <= MAXN; k++)
fill_cell(k);
}
inline void show()
{
cout << d[n][k] << endl;
}
int main()
{
int nCase;
cin >> nCase;
set_dynamic_table();
for (int i = 0; i < nCase; i++)
{
cin >> n >> k;
show();
}
return 0;
}










