Düzbucaqlı kəsmək#11722

Düzbucaqlı kəsmək (Həll təhlili)

Tutaq ki, f(a, b) — a \times b ölçülü düzbucaqlını kvadratlara kəsmək üçün lazım olan minimum addım sayıdır. Bu dəyəri hüceyrəsində saxlayacağıq.

Əgər düzbucaqlı artıq kvadratdırsa (a = b), kəsmələr tələb olunmur, buna görə f(a, a) = 0.

a \times b ölçülü düzbucaqlı ya şaquli, ya da üfüqi kəsimlə kəsilə bilər. Əvvəlcə şaquli kəsimi nəzərdən keçirək.

Şaquli kəsimdə a \times b ölçülü düzbucaqlı iki düzbucaqlıya: a \times k və a \times (b - k) bölünür. Alınan düzbucaqlıların deqradasiyaya uğramaması üçün 1 \le k < b şərti yerinə yetirilməlidir. Sonra bu düzbucaqlıların hər biri üçün rekursiv olaraq məsələni həll edirik və nəticəyə əlavə edirik, çünki bir şaquli kəsim etdik. Ən kiçik olan -ni elə seçirik ki, f(a, k) + f(a, b - k) + 1 cəmi minimal olsun:

f(a, b) = \min_{\substack{1 \le k < b}} (f(a, k) + f(a, b - k)) + 1

Üfüqi kəsim vəziyyəti üçün oxşar düstur alırıq:

f(a, b) = \min_{\substack{1 \le k < a}} (f(k, b) + f(a - k, b) + 1

Bu iki variant arasında minimal dəyəri seçmək qalır.

Nümunə

Birinci testdə kəsim tələb olunur:

Alqoritmin həyata keçirilməsi

Sabitlər və işçi massiv elan edirik.

#define MAX 501
#define INF 0x3F3F3F3F

int dp[MAX][MAX];

f(a, b) funksiyası a \times b ölçülü düzbucaqlını kvadratlara kəsmək üçün lazım olan minimum addım sayını qaytarır.

int f(int a, int b)
{

Əgər düzbucaqlı artıq kvadratdırsa (a = b), kəsmələr tələb olunmur.

  if (a == b) return 0;

Əgər f(a, b) dəyəri hələ hesablanmayıbsa (dp[a][b] = ∞), onu hesablayırıq.

  if (dp[a][b] == INF)
  {

Bütün mümkün şaquli kəsimləri həyata keçiririk.

    for (int k = 1; k < b; k++)
      dp[a][b] = min(dp[a][b], f(a, k) + f(a, b - k) + 1);

Bütün mümkün üfüqi kəsimləri həyata keçiririk.

    for (int k = 1; k < a; k++)
      dp[a][b] = min(dp[a][b], f(k, b) + f(a - k, b) + 1);
  }

Nəticəni f(a, b) = dp[a][b] olaraq qaytarırıq.

  return dp[a][b];
}

Proqramın əsas hissəsi. Düzbucaqlının və ölçülərini oxuyuruq.

scanf("%d %d", &a, &b);

Cavabı hesablayırıq və çap edirik.

memset(dp, 0x3F, sizeof(dp));
printf("%d\n", f(a, b));