CTDL và giải thuật - Giải thuật Qui hoạch động
Hải vừa được trúng thưởng cực lớn trong một trò chơi. Ban tổ chức đã chuẩn bị sẵn cho Hải n
món quà có giá trị lần lượt là a0, a1, ..., an-1
.
Ban tổ chức cho phép Hải chọn quà theo luật như sau:
- Mỗi lượt chỉ được chọn
1
món quà. - Nếu lượt này đã chọn món quà thứ
k
thì lượt sau chỉ được chọn các phần quà từk + 1
đếnn - 1
. - Ở lượt chọn quà lẻ (lượt
1
, lượt3
,...) thì Hải được chọn bất kỳ phần quà giá trị tùy ý. - Ở lượt chọn quà chẵn (lượt
2
, lượt4
,..) thì Hải bắt buộc phải chọn phần quà có cùng giá trị với phần quà ngay trước đó mà Hải đã chọn.
Hãy tìm và in ra tổng giá trị lớn nhất của các phần quà mà Hải có thể chọn.
Ví dụ:
- Test mẫu 1:
Input Output 3
2 3 24
Vớia = [2, 3, 2]
, thìchooseGifts(a) = 4
.
Giải thích:- Lượt
1
Hải chọn phần quà có giá trịa[0] = 2
, lượt2
Hải chọn phần quà có giá trịa[2] = 2
.
- Lượt
- Test mẫu 2:
Input Output 5
10 6 7 6 113
Vớia = [10, 6, 7, 6, 1]
, thìchooseGifts(a) = 13.
Hướng dẫn bài tập.
Sử dụng giải thuật quy hoạch động.
Gợi ý: Dùng dãy s[n][2]
để lưu tổng lớn nhất:
s[i][0]
: Tổng lớn nhất với lượt chọn lẻ kết thúc tạii
.s[i][1]
: Tổng lớn nhất với lượt chọn chẵn kết thúc tạii
.
Code mẫu:
Ngôn ngữ C++:
#include<iostream>
using namespace std;
int s[10001][2];
int a[10001];
int chooseGifts(int a[], int n)
{
for (int i = 0; i < n; i++){
s[i][0] = a[i];
s[i][1] = -1;
}
for (int i = 1; i < n; i++){
for (int j = 0; j < i; j++)
if (a[j] == a[i] && s[j][0] + a[i] > s[i][1])
s[i][1] = s[j][0] + a[i];
for (int j = 0; j < i; j++)
if (s[j][1] + a[i] > s[i][0])
s[i][0] = s[j][1] + a[i];
}
int max = -1;
for (int i = 0; i < n; i++)
for (int j = 0; j < 2; j++)
if (s[i][j] > max) max = s[i][j];
return max;
}
int main(){
int n, x;
cin >> n;
for (int i = 0; i < n; i++){
cin >> a[i];
}
cout << chooseGifts(a, n);
return 0;
}