Optimal qiyməti ikili axtarış vasitəsilə tapacağıq. Aydındır ki, o, -dən kiçik ola bilməz (çünki massivdəki rəqəmlər təbii ədədlərdir) və bütün elementlərin cəmini keçə bilməz. Sərhədləri quraq: sol = 1, sağ = bütün massiv ədədlərinin cəmi. Onda cavab mütləq [sol; sağ] aralığında yerləşir.
Yardımçı alt məsələyə baxaq: massivə elə altmassivə bölmək olarmı ki, bütün altmassivin içindəki maksimal cəm verilmiş s_0 dəyərindən artıq olmasın? Əgər massivdə s_0-dan böyük ən azı bir element varsa, belə bölmə mümkün deyil. Digər hallarda, element cəmi s_0-dan artıq olmayan altmassivləri ardıcıl formalaşdıracağıq. Nəticədə -dan çox olmaması şərtilə altmassiv alınarsa, belə bölmə mümkündür.
Misal
İkinci misalda, müxtəlif s_0 dəyərlərində massivə altmassivlərə bölməyi nəzərdən keçirək:
Alqoritmin reallaşdırılması
MAX = 10^6 sabitinin və işçi massiv -in elan edilməsi.
#define MAX 1000000
int m[MAX];f funksiyası elə qaytarır ki, massivə elə altmassivə bölmək olar ki, bütün altmassivlərin içində maksimal cəm verilmiş s_0 dəyərindən artıq olmasın.
int f(long long s0)
{
long long sum = 0;
int cnt = 1;
for (int i = 0; i < n; i++)
{Əgər massivdə hansısa element s_0-dan böyükdürsə, belə bölmə mümkün deyil.
if (m[i] > s0) return 0;Cari altmassivin cəmini hesablamaq.
sum += m[i];Cari cəm s_0-ı üstələdikdə, altmassivlərin sayğacını artırırıq və növbəti altmassivin cəmini toplamağa başlayırıq.
if (sum > s0)
{
sum = m[i];
cnt++;
}
}Əgər massiv -dan çox olmayan altmassivə bölünə bilərsə, deməli, onu tam k~(k \le n) altmassivə bölmək olar.
if (cnt <= k) return 1;
return 0;
}Proqramın əsas hissəsi. Giriş verilənlərini oxuyuruq. sağ dəyişənində bütün massiv elementlərinin cəmini hesablayırıq.
scanf("%d %d", &n, &k);
left = 1; right = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &m[i]);
right += m[i];
}Axtarılan minimal maksimum altmassiv cəm [sol; sağ] aralığında yerləşir. İkili axtarışı bu intervalda başlatırıq.
while (left < right)
{
mid = (left + right) / 2;
if (f(mid) == 1)
right = mid;
else
left = mid + 1;
}Cavabı çap edirik.
printf("%lld\n", left);