Vasya və matrisa#3535

Vasya və matrisa (Həll təhlili)

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:

dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + a[i][j]

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:

dp[i + w - 1][j + h - 1] - dp[i + w - 1][j - 1] - dp[i - 1][j + h - 1] + dp[i - 1][j - 1]

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

48 - 19 - 19 + 7 = 17

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);