Tutaq ki, dp_k[s] — yalnız ilk növ əşyadan istifadə etməyə icazə verildikdə, çəkisi -dən çox olmayan yükün maksimal dəyəridir.
Çəkisi olan yükü tərtib edərkən iki mümkün variantı nəzərdən keçirək:
-cı növ əşyadan istifadə etməmək: bu halda optimal qiymət dəyişməz, yəni
-cı növ əşyadan istifadə etmək: onda onun w_k çəkisi bel çantasının tutumunun bir hissəsini tutacaq, dəyər isə v_k qədər artacaq, yəni
Yükün dəyərini maksimuma çatdırmaq tələb olunduğundan, aşağıdakı rekurrent münasibəti alırıq:
Əsas hallar:
Tutaq ki, f(k, s) funksiyası ilk növ əşyadan istifadə edərək, çəkisi -dən çox olmayan bel çantasına yığıla bilən yükün maksimal dəyərini hesablayır. Onda aşağıdakı rekurrent münasibət doğrudur:
Qalır ki, f(k, s) funksiyasının qiymətini memoizasiya istifadə edərək hesablayaq.
Alqoritmin realizasiyası
İşçi massivləri elan edək:
— -ci növ əşyanın çəkisi;
— -ci növ əşyanın dəyəri;
— çəkisi -dən çox olmayan yükün maksimal dəyəri;
#define MAXW 252
#define MAXN 37
int w[MAXN], p[MAXN];
int dp[MAXW];Giriş məlumatlarını oxuyuruq.
scanf("%d %d", \&s, \&n);
for (i = 0; i \< n; i++)
scanf("%d %d", \&w[i], \&p[i]);növ əşyanı ardıcıl olaraq emal edirik.
for (k = 0; k \< n; k++)
{növ əşyalardan istifadə etmə imkanını nəzərə alaraq, massivinin qiymətlərini yenidən hesablayırıq. Hər növ əşyanın sayı məhdudlaşdırılmadığından, hər əşya bir neçə dəfə seçilə bilər.
for (i = w[k]; i \<= s; i++)
dp[i] = max(dp[i], dp[i - w[k]] + p[k]);
}Cavabı çap edirik.
printf("%d\n", dp[s]);Alqoritmin realizasiyası — rekursiya
İşçi massivləri elan edək:
— -ci növ əşyanın çəkisi;
— -ci növ əşyanın dəyəri;
— çəkisi -dən çox olmayan yükün maksimal dəyəri;
#define MAXW 252
#define MAXN 37
#define INF 2000000000
int w[MAXN], v[MAXN];
int dp[MAXN][MAXW];f(k, s) funksiyası ilk növ əşyadan istifadə edərək, çəkisi -dən çox olmayan bel çantasına yığıla bilən yükün maksimal dəyərini hesablayır.
int f(int k, int s)
{Əgər k = 0 və ya s = 0 olarsa, bel çantası boşdur və onun dəyəri -a bərabərdir.
if (k == 0 || s == 0) return 0;Əgər olarsa, biz icazə verilən çəkini aşmışıq və bu variantın mənası yoxdur. Buna görə qaytarırıq ( — müəyyən bir böyük ədəddir).
if (s \< 0) return -INF;Əgər f(k, s) qiyməti artıq hesablanıbsa, onu qaytarırıq.
if (dp[k][s] != -1) return dp[k][s];f(k, s) qiymətini hesablayırıq və onu dp[k][s]-də yadda saxlayırıq.
return dp[k][s] = max(f(k - 1, s), f(k, s - w[k]) + v[k]);
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
scanf("%d %d", \&s, \&n);
for (i = 1; i \<= n; i++)
scanf("%d %d", \&w[i], \&v[i]);Cavabı hesablayır və çap edirik.
memset(dp, -1, sizeof(dp));
printf("%d\n", f(n, s));