책 복사하기 1, 2(정올) / 백준

책 1 복사

https://www.acmicpc.net/problem/3487

3487호: 복사 서적

입력은 N개의 경우로 구성됩니다. 입력의 첫 번째 줄에는 양의 정수 N만 포함됩니다. 그런 다음 사례가 이어집니다. 각 케이스는 정확히 두 줄로 구성됩니다. 첫 번째 행에는 두 개의 정수 m과 k, 1 ≤ k ≤ m ≤ 500이 있습니다. 두 번째 행에는 li

www.acmicpc.net

https://zoosso.645

(중골)정올 1156권 2권

출처: http://www.jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=436&sca=40 Approach 이진 검색(2분 검색) 이진 검색(2분 검색) 이진 검색(2분 검색) Search) From Sorted Data 대상 값을 찾을 때 사용하는 탐색기

zoosso.tistory.com

https://howtoliveworldnice.429

백준 3487 책 베끼기

프레젠테이션 자료에 대한 Copying Book 2 문제는 파라메트릭 검색 솔루션을 강제로 복사하는 책에 M,K 범위를 추가하는 문제입니다. www.acmicpc.net/problem/3487 #3487: Copying books 입력은 N개의 경우로 구성됩니다. 첫번째

howtoliveworldnice.tistory.com

페이지 수가 결정되면 필요한 작가 수를 알 수 있습니다.

필요한 마커의 수는 가장 두꺼운 책의 페이지 수부터 순차적으로 계산되고 그 수가 k보다 작으면 그 수가 피치 기준이 됩니다.

공격

1. 프론트 직원을 적게 사용하기 때문에 뒤쪽에서 채웁니다.

2. 앞에서 1권도 배정받지 못한 직원이 있으면 앞에서 1권을 배정받는다.

#if 0
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#define ll long long
using namespace std;

//ll book(511);
//ll N, K;
//
//int check(ll p)
//{
//	ll sum = 0, cnt = 1;
//	for (int i = 1; i <= N; i++)
//	{
//		sum += book(i);
//		if (sum > p)
//		{
//			if (++cnt > K) return 0;
//			sum = book(i);
//		}
//	}
//	return 1;
//}
//int b_search(int s, int e)
//{
//	if (s > e) return s;
//	ll m = (s + e) / 2;
//	if (check(m)) return b_search(s, m - 1);
//	return b_search(m + 1, e);
//}
//void output(int ans)
//{
//	ll i, sum = 0, cnt = 1, div(511) = { 0 };
//	for (int i = N; i > 0; i--)
//	{
//		sum += book(i);
//		if (sum > ans)
//		{
//			cnt++;
//			sum = book(i);
//			div(i) = 1;
//		}
//	}
//	for (int i = 1; cnt < K; i++)
//	{
//		if (div(i) == 0)
//		{
//			div(i) = 1;
//			cnt++;
//		}
//	}
//	for (int i = 1; i <= N; i++)
//	{
//		printf("%d ", book(i));
//		if (div(i) == 1) printf("/ ");
//	}
//	printf("\n");
//}
//int main(void)
//{
//	freopen("input.txt", "r", stdin);
//	ll T, low, high, ans;
//	scanf("%d", &T);
//	while (T--)
//	{
//		low = high = 0;
//		scanf("%d %d", &N, &K);
//		for (int i = 1; i <= N; i++)
//		{
//			scanf("%d", &book(i));
//			high += book(i);
//			if (low < book(i)) low = book(i);
//		}
//		ans = b_search(low, high);
//		output(ans);
//	}
//}

int TC;
int M;
int K;

bool check(int mid, vector<int> book)
{
	ll cnt = 1;
	ll sum = 0;
	for (int i = 1; i <= M; i++)
	{
		sum += book(i);
		if (sum > mid)
		{
			if(++cnt > K) return 0;
			sum = book(i);
		}
	}
	return (cnt <= K);
}
int main(void)
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	freopen("input.txt", "r", stdin);

	cin >> TC;
	while (TC--)
	{
		cin >> M >> K;
		
		ll tmp;
		ll low = 0;
		ll high = 0;
		ll ans = 0;
		vector<int> book;
		book.push_back(0);
		for (int i = 1; i <= M; i++)
		{
			cin >> tmp;
			book.push_back(tmp);
			if (tmp > low) low = tmp;
			high += tmp;
		}

		while (low <= high)
		{
			ll mid = (low + high) / 2;
			if (check(mid, book))
			{
				ans = mid;
				high = mid - 1;
			}
			else
				low = mid + 1;
		}

		ll sum = 0;
		ll cnt = 1;
		vector<int> div(510,0);
		for (int i = M; i > 0; i--)
		{
			sum += book(i);
			if (sum > ans)
			{
				cnt++;
				sum = book(i);
				div(i) = 1;
			}
		}
		for (int i = 1; cnt < K; i++)
		{
			if (div(i) == 0)
			{
				div(i) = 1;
				cnt++;
			}
		}
		for (int i = 1; i <= M; i++)
		{
			cout << book(i) << ' ';
			if (div(i) == 1) cout << "/ ";
		}
		cout << '\n';
	}
	return 0;

}
#endif


문제는 이런 식으로 백준에게 제출하면 절반만 성공한다는 점이다. 그 뒤에 있는 것은 잘못된 것으로 밝혀졌습니다.

그 이유는 백준님의 문제가 책정리2 형식이고, 기본적으로 10만 권의 책을 등록하여 시간이 흘렀기 때문입니다.

복사 책 2

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#define ll long long
using namespace std;

int TC;
int M;
int K;
ll low = 0, high = 0, ans = 0;
vector<int> book(100010);

bool check(ll mid)
{
	ll cnt = 1;
	ll sum = 0;
	for (int i = 1; i <= M; i++)
	{
		sum += book(i);
		if (sum > mid)
		{
			if (++cnt > K) return 0;
			sum = book(i);
		}
	}
	return (cnt <= K);
}
void output(int idx, ll sum, int ck)
{
	if (idx < 1) return;
	if (sum + book(idx) > ans || idx <= ck)
	{
		output(idx - 1, book(idx), ck - 1);
		printf("%d / ", book(idx));
	}
	else {
		output(idx - 1, sum + book(idx), ck);
		printf("%d ", book(idx));
	}
		
}
int main(void)
{
	//freopen("input.txt", "r", stdin);

	scanf("%d %d", &M, &K);

	ans = 0;
	low = high = 0;
		
	for (int i = 1; i <= M; i++)
	{
		scanf("%d", &book(i));
		if (book(i) > low) low = book(i);
		high += book(i);
	}

	while (low <= high)
	{
		ll mid = (low + high) / 2;
		if (check(mid))
		{
			ans = mid;
			high = mid - 1;
		}
		else
			low = mid + 1;
	}

	output(M, 0, K-1);

	return 0;

}
#endif