Binaları onların hündürlüyünə görə çeşidləyək, belə ki h_1 \le h_2 \le ... \le h_n bərabərsizliyi ödənilsin. Əgər bir neçə bina eyni hündürlüyə malikdirsə, onları əlavə və ya çıxarmaq qiymətinə görə azalan şəkildə də sıralayırıq.
Bütün binaları h_x~(1 \le x \le n) hündürlüyə gətirmək üçün lazım olan qiyməti nəzərdən keçirək. O, bərabərdir
Bu qiyməti təsvir edən funksiyası qapalı və qlobal minimuma malikdir ki, bu da üçlük axtarışı ilə tapıla bilər.
Nümunə
İlk nümunəni nəzərdən keçirək. Binaları onların hündürlüyünə görə çeşidləyək:
Binaların mümkün bütün hündürlükləri üçün funksiyasının qiymətlərini tapaq:
f(1) = (1 - 1) \cdot 30 + (2 - 1) \cdot 10 + (3 - 1) \cdot 20 + (4 - 1) \cdot 40 = 170,
f(2) = (2 - 1) \cdot 30 + (2 - 2) \cdot 10 + (3 - 2) \cdot 20 + (4 - 2) \cdot 40 = 130,
f(3) = (3 - 1) \cdot 30 + (3 - 2) \cdot 10 + (3 - 3) \cdot 20 + (4 - 3) \cdot 40 = 110,
f(4) = (4 - 1) \cdot 30 + (4 - 2) \cdot 10 + (4 - 3) \cdot 20 + (4 - 4) \cdot 40 = 130
funksiyasının minimum qiyməti x = 3 olduğu halda əldə edilir; bu halda f(3) = 110.
Alqoritmin tətbiqi
Hər bir bina hündürlüyünə və mərtəbəni əlavə və ya çıxarmaq üçün xərci var. Bina məlumatları massivində saxlanılır.
#define MAX 100001
struct Building
{
int h, cost;
};
Building b[MAX];cmp funksiyası binaların çeşidlənməsi üçün komparator rolunu oynayır. İlk növbədə binalar hündürlüklərə görə artan şəkildə, eyni hündürlükdə olan binalar isə xərclərinə görə çeşidlənir.
int cmp(Building a, Building b)
{
if (a.h == b.h)
return a.cost < b.cost;
return a.h < b.h;
}f funksiyası bütün binaları bina ilə eyni hündürlüyə gətirmək üçün lazım olan qiymətləri hesablayır.
long long f(int x)
{
long long ret = 0;
for (int i = 1; i <= n; i++)
ret += 1LL * abs(b[x].h - b[i].h) * b[i].cost;
return ret;
}ternary_search funksiyası üçlük axtarışı vasitəsilə [left; right] intervalında -ın minimal olduğu qiymətini tapır. Başlanğıcda interval [left; right] = [1; n] olar.
long long ternarySearch(int left, int right)
{
while (right - left >= 3)
{
int a = left + (right - left) / 3;
int b = left + 2 * (right - left) / 3;
if (f(a) > f(b))
left = a;
else
right = b;
}və arasındakı fərq -dən böyük deyil. Bu halda [left; right] intervalında -ın minimal qiymətini tam iterasiya ilə tapırıq.
long long res = f(left++);
while (left <= right)
res = min(res, f(left++));
return res;
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
scanf("%d", &n);
for (i = 1; i <= n; i++)
scanf("%d", &b[i].h);
for (i = 1; i <= n; i++)
scanf("%d", &b[i].cost);Binaları çeşidləyirik.
sort(b + 1, b + n + 1, cmp);Cavabı hesablayırıq və çıxış edir. Binalar -dən -ə kimi nömrələnir.
printf("%lld\n", ternarySearch(1, n));