U E D R , A S I H C RSS

금고/문보창

금고

바로 코드 짜면 저번처럼 �해버릴 것만 같아서, �화� 만들고, 간단히 �명까지 하고 코드를 짰다. 층수 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 � �용하여 값� 구할 수 있다.

코드

~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;
}
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:46
Processing time 0.0035 sec