Verilən — giriş düzbucaqlı matrisa olsun. Eyni ölçüdə olan ikiölçülü massivini yaratmaq lazımdır, burada dp[i][j] — və nöqtələrində yerləşən düzbucaqlının tərkibində olan elementlərin cəmi olacaq. Bu dəyərlər aşağıdakı formada hesablana bilər:
massivinin w \times h ölçülü altmatrisasına nəzər salaq. Onun qarşı tərəflərini və (i + w - 1, j + h - 1) koordinatlarında olmaqla qəbul edək.
Onda altmatrisanın içindəki bütün ədədlərin cəmi belə hesablanır:
Məsələni tam təkrarlı yol ilə həll edək. Altmatrisanın mümkün olan bütün w \times h ölçülərini, həmçinin altmatrisanın sol üst köşə koordinatlarını nəzərdən keçiririk. massivindən istifadə edərək, cari altmatrisanın daxilindəki ədədlərin cəmini sabit zamanda müəyyən edirik. Əgər bu cəm -dan çox deyilsə, belə altmatrisaların içində maksimum sahəni yadda saxlayırıq.
Amma belə bir təkrar O(n^4) zaman fəzasında işləyir, bu da çox uzundur. Bunu O(n^3logn)-ə qədər sürətləndirə bilərik, altmatrisanın eni üçün ikitərəfli axtarışdan istifadə edərək.
Sol üst köşə nöqtəsini sabitləyirik. g(w, h) funksiyası ilə və (i + w - 1, j + h - 1) köşə daxilindəki elementlərin cəmini təyin edək. Əgər hündürlüyü sabitləyərək, eni kimi qəbul etsək, g(w, h) funksiyası -yə görə artan olacaq, çünki ilkin matrisa mənfi olmayan tam ədədlərdən ibarətdir. Bu, g(w, h) \le k olan maksimum dəyərini tapmaq üçün ikitərəfli axtarışdan istifadə etməyə imkan verir.
Misal
Məsələn, və nöqtələr ilə ifadə olunan altmatrisanın daxilindəki ədədlərin cəmi
Alqoritmin icrası
Giriş matrisasını massivində saxlayırıq.
#define MAX 210
int a[MAX][MAX], dp[MAX][MAX];Funksiya f(w, h) w \times h ölçüsündəki bir altmatrisanın mövcudluğunu, sayları -dan çox olmayacaq şəkildə yoxlayır. Bütün mümkün sol köşə koordinatlarını nəzərdən keçirərək və massivindən istifadə edərək verilmiş düzbucaqlı daxilindəki ədədlərin cəmini sabit zamanda hesablayırıq.
int f(int w, int h)
{
for (int i = 1; i + w - 1 <= n; i ++)
for (int j = 1; j + h - 1 <= m; j ++)
if (dp[i + w - 1][j + h - 1] - dp[i + w - 1][j - 1] –
dp[i - 1][j + h - 1] + dp[i - 1][j - 1] <= k) return 1;
return 0;
};Proqramın əsas hissəsi. Giriş matrisasını oxuyuruq.
scanf("%d %d %d",&n,&m,&k);
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
scanf("%d",&a[i][j]);Verilən giriş matrisasına əsasən dəst matrisa yaradırıq.
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + a[i][j];Mümkün altmatrisanın eni olan dəyərlərini nəzərdən keçiririk.
answer = 0;
for (w = 1; w <= n; w++)
{Altmatrisanın uzunluğunu [l; r] aralığında ikitərəfli axtarışla nəzərdən keçiririk.
l = 1; r = m;
while (l < r)
{
mid = (l + r) / 2;w \times mid ölçülü altmatrisanın sol üst köşəsi -ın bütün mümkün mövqelərini nəzərdən keçiririk. Əgər hər hansı bir mövqe mövcud olsa və altmatrisanın daxilində olan ədəd cəmi -dan çox deyilsə, nəticənin sahə dəyərini ilə yeniləyirik.
if (f(w,mid))
{
answer = max(answer, w * mid);
l = mid + 1;
}
else r = mid;
}
mid = (l + r) / 2;
if (f(w,mid))
answer = max(answer, w * mid);
};Tapılan maksimum altmatrisanın sahəsini çıxardırıq.
printf("%d\n",answer);