Tutaq ki, massivində kəsilmə nöqtələri var: m_1, ..., m_n. Başlanğıc və son nöqtələri əlavə edək: m_0 = 0, m_{n+1} = l.
Tutaq ki, f(a, b) funksiyası m_a-dan m_b-ya qədər olan çubuq parçasını minimum kəsilmə xərci ilə verir ki, daxilindəki zəruri kəsilmə nöqtələrini də nəzərə alaq. [m_a; m_{a + 1}] intervallı daxilində kəsilmə nöqtəsi yoxdur, buna görə f(a, a + 1) = 0. Məsələnin cavabı f(0, n + 1) olacaq. Hesablanmış f(a, b) dəyərlərini massivinin hücrələrində saxlayırıq.
Tutaq ki, çubuq parçası [m_a, m_b] bir neçə hissəyə kəsilməlidir. İlk kəsimi m_i~(a < i < b) nöqtəsində edəriksə, kəsimin xərci m_b - m_a təşkil edəcək. Sonra qalan parçaları müvafiq olaraq f(a, i) və f(i, b) xərci ilə kəsmək lazımdır. dəyərini ümumi xərci minimallaşdırmaq üçün seçmək lazımdır:
Nümunə
İkinci testə baxaq. Çubuq uzunluğu olan bir kəsim metodunu 10 + 7 + 3 + 3 = 23 xərci ilə göstərək:
Optimal kəsim metodunu 10 + 6 + 3 + 3 = 22 xərci ilə nəzərdən keçirək:
Alqoritmin icrası
Sabitləri və işçi massivlərini elan edək.
#define MAX 55
#define INF 0x3F3F3F3F
int dp[MAX][MAX];
int m[MAX];f(a, b) funksiyası, daxilindəki kəsim nöqtələrini nəzərə alaraq intervalında çubuq parçasının kəsilməsinin minimum xərci qaytarır.
int f(int a, int b)
{Əgər a + 1 = b olarsa, intervalında kəsim nöqtəsi yoxdur. qaytarırıq.
if (b - a == 1) return 0;Əgər f(a, b) dəyəri artıq hesablanmışsa, onu qaytarırıq.
if (dp[a][b] != INF) return dp[a][b];i~(a < i < b) nöqtəsində kəsim edirik. Xərci aşağıdakı kimi hesablayırıq:
for (int i = a + 1; i < b; i++)
dp[a][b] = min(dp[a][b], m[b] - m[a] + f(a, i) + f(i, b));Nəticəni f(a, b) = dp[a][b] olaraq qaytarırıq.
return dp[a][b];
}Proqramın əsas hissəsi. Hər test üçün giriş məlumatlarını oxuyuruq.
while(scanf("%d",&l),l)
{
scanf("%d",&n);Başlanğıc və son kəsim nöqtələrini əlavə edək: m_0 = 0, m_{n+1} = l.
m[0] = 0; m[n+1] = l;
for(i = 1; i <= n; i++)
scanf("%d",&m[i]);Məxəzini massivini alqı-initiatiaiz edək.
memset(dp,0x3F,sizeof(dp));Cavabı hesablayıb çap edirik.
printf("Minimum kəsim %d.\n",f(0,n+1));
}