Maximum Sum Increasing Subsequence (MSIS) คือ subsequence ที่:
- เรียงลำดับเพิ่มขึ้น (Increasing)
- มีผลรวมของสมาชิกมากที่สุด (Maximum Sum)
ตัวอย่าง Input และ Output
Input: {3, 2, 6, 4, 5, 1}
Output: Maximum Sum Subsequence is: 3 4 5
(Sum = 12, ซึ่งมากกว่า {2, 6} = 8 หรือ {3, 6} = 9)
อัลกอริทึม Dynamic Programming
ฟังก์ชัน maxSumSubSeq(array, n)
แนวคิด:
ใช้ Vector of Vectors: subSeqLen[i] = MSIS ที่ลงท้ายด้วย arr[i] (เก็บ subsequence จริง ไแค่ความยาว)
ขั้นตอน:
- สร้าง
vector> subSeqLen(n) subSeqLen[0] = {arr[0]}- for i = 1 ถึง n-1:
- for j = 0 ถึง i-1:
- ถ้า
arr[i] > arr[j]และsum(subSeqLen[i]) < sum(subSeqLen[j]) - →
subSeqLen[i] = subSeqLen[j](คัดลอก subsequence ที่ดีกว่า)
- ถ้า
subSeqLen[i].push_back(arr[i])(ต่อท้าย arr[i])
- for j = 0 ถึง i-1:
- หา
res= subsequence ที่มี sum มากที่สุดจากsubSeqLen - พิมพ์
res
ตัวอย่างโค้ด C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int findAllSum(vector arr) {
int sum = 0;
for(int i = 0; i < arr.size(); i++) sum += arr[i];
return sum;
}
void maxSumSubSeq(int arr[], int n) {
vector> subSeqLen(n);
subSeqLen[0].push_back(arr[0]);
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if ((arr[i] > arr[j]) && (findAllSum(subSeqLen[i]) < findAllSum(subSeqLen[j])))
subSeqLen[i] = subSeqLen[j];
}
subSeqLen[i].push_back(arr[i]);
}
vector res = subSeqLen[0];
for(int i = 0; i < subSeqLen.size(); i++)
if (findAllSum(subSeqLen[i]) > findAllSum(res))
res = subSeqLen[i];
for(int i = 0; i < res.size(); i++)
cout << res[i] << " ";
cout << endl;
}
int main() {
int arr[] = {3, 2, 6, 4, 5, 1};
int n = 6;
cout << "The Maximum Sum Subsequence is: ";
maxSumSubSeq(arr, n);
return 0;
}
Output
The Maximum Sum Subsequence is: 3 4 5
ความซับซ้อน
- Time: O(n²) (หากคำนวณ sum ทุกครั้ง จะเป็น O(n³) - ควรเก็บ sum ไว้แยก)
- Space: O(n²) - เก็บ subsequence ทั้งหมด
การเพิ่มประสิทธิภาพ (Optimized O(n²) Time, O(n) Space)
int maxSumIS(int arr[], int n) {
int msis[n];
for (int i = 0; i < n; i++) msis[i] = arr[i];
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
if (arr[i] > arr[j] && msis[i] < msis[j] + arr[i])
msis[i] = msis[j] + arr[i];
return *max_element(msis, msis+n);
}
เวอร์ชันนี้เก็บแค่ ผลรวม ไม่เก็บ subsequence จริง เร็วกว่าและประหยัดหน่วยความจำ