Trò chơi với băng số
2017-08-02Bài gốc
Đề bài
Trò chơi với băng số là trò chơi tham gia trúng thưởng được mô tả như sau: Có một băng hình chữ nhật được chia ra làm n ô vuông, đánh số từ trái qua phải bắt đầu từ 1. Trên ô vuông thứ i người ta ghi một số nguyên dương ai, i = 1, 2, …, n. Ở một lượt chơi, người tham gia trò chơi được quyền lựa chọn một số lượng tùy ý các ô trên băng số. Giả sử theo thứ tự từ trái qua phải, người chơi lựa chọn các ô i1, i2, …, ik. Khi đó điểm số mà người chơi đạt được sẽ là:
ai1 - ai2 + … + (-1)(k-1)aik
Yêu cầu: Hãy tính số điểm lớn nhất có thể đạt được từ một lượt chơi.
Giới hạn:
- 1 ≤ n ≤ 106
- 0 ≤ ai ≤ 104
Định dạng test
Input:
- Dòng đầu tiên chứa số nguyên dương n ( n ≤ 106 ) là số lượng ô của băng số.
- Dòng thứ hai chứa n số nguyên dương ai ghi trên băng số. Các số liên tiếp trên cùng dòng được ghi cách nhau bởi ít nhất một dấu cách.
Output:
- Một số nguyên duy nhất là số điểm lớn nhất có thể đạt được từ một lượt chơi.
Ví dụ:
Thuật toán
DP: Tạo mảng dp[N][2] với ý nghĩa:
- dp[i][0]: là số điểm tối đa nếu ta chọn một số lẻ các băng số trong đoạn [1, i] (kết thúc bởi việc trừ một băng số).
- dp[i][1]: là số điểm tối đa nếu ta chọn một số chẵn các băng số trong đoạn [1, i] (kết thúc bởi việc cộng một băng số).
Lấy ví dụ tại phần tử thứ i, muốn tính dp[i][0], ta có 3 trường hợp sau đây:
- Không chọn ai vào băng số, dp[i][0] = dp[i-1][0].
- Chọn duy nhất ai vào băng số, dp[i][0] = -a[i].
- Chọn ai vào băng số như là phần tử tiếp theo của băng số đã chọn trước đó: dp[i][0] = dp[i-1][1] - a[i].
Như vậy dp[i][0] là giá trị lớn nhất trong 3 trường hợp trên, hoàn toàn tương tự cho dp[i][1].
Giá trị khởi tạo: dp[1][0] = 0, dp[1][1] = a[1].
Source code
Ngôn ngữ: C++.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const int N = 1e6 + 5;
int n;
ll f[N][2], a[N];
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// input
cin >> n;
FOR(i,1,n) cin >> a[i];
// dp init
f[1][0] = 0;
f[1][1] = a[1];
// dp
FOR(i,2,n) {
f[i][0] = max(f[i-1][0], max(-a[i], f[i-1][1] - a[i]));
f[i][1] = max(f[i-1][1], max(a[i], f[i-1][0] + a[i]));
}
cout << max(f[n][0], f[n][1]);
return 0;
}
Độ phức tạp
O(N)