倒卖战利品
倒卖战利品
http://www.nowcoder.com/questionTerminal/2f8a06421eea4dfe837453c8be6cb210
> 首先要注意,题目中的条件有误,应该是严格大于而不是大于等于。
排序+动态规划(暴力搜索)
首先按照第一个维度将数组从小到大排序,第一个维度相同的,按照第二个维度从小到达排序。这样以来,问题就被转换为最大上升子序列问题。使用动态规划求解即可。
状态定义为:以第i个元素结尾的上升子序列的最大长度。
下面是第一种动态规划的解法,该解法超时。
#include <vector>
#include <iostream>
#include <limits.h>
#include <functional>
#include <algorithm>
using namespace std;
struct Compare {
bool operator () (const vector<int>& item1, const vector<int>& item2) {
if (item1[0] == item2[0]) {
return item1[1] < item2[1];
} else {
return item1[0] < item2[0];
}
}
};
int main() {
int n;
cin >> n;
vector<vector<int>> items(n, vector<int>(2, 0));
for (int i = 0; i < n; i++) {
scanf("%d%d", &items[i][0], &items[i][1]);
}
sort(items.begin(), items.end(), Compare());
vector<int> dp_table(n, 1);
int max_sold = 1;
for (int i = 1; i < n; i++) {
int current_max_length = 1;
int length;
for (int j = 0; j < i; j++) {
if (items[i][1] <= items[j][1]) {
continue;
}
length = dp_table[j] + 1;
if (length > current_max_length) {
current_max_length = length;
}
}
if (current_max_length > max_sold) {
max_sold = current_max_length;
}
dp_table[i] = current_max_length;
}
cout << max_sold << endl;
return 0;
} 排序+动态规划(二分查找+贪心)
在动态规划中,为了更快地进行查找,需要更改状态定义。将状态dp[i]定义为长度为i + 1的上升子序列的尾元素的最小值。在进行状态转移时,比较复杂,建议参考最长上升子序列。
代码如下:
#include <vector>
#include <iostream>
#include <limits.h>
#include <functional>
#include <algorithm>
using namespace std;
struct Compare {
bool operator () (const vector<int>& item1, const vector<int>& item2) {
if (item1[0] == item2[0]) {
return item1[1] < item2[1];
} else {
return item1[0] < item2[0];
}
}
};
int main() {
int n;
cin >> n;
vector<vector<int>> items(n, vector<int>(2, 0));
for (int i = 0; i < n; i++) {
scanf("%d%d", &items[i][0], &items[i][1]);
}
sort(items.begin(), items.end(), Compare());
vector<int> dp_table(n, 0); // dp_table[i]表示长度为i + 1的上升子序列末尾的最小值
dp_table[0] = items[0][1];
int end = 0;
for (int i = 1; i < n; i++) {
if (items[i][1] > dp_table[end]) {
end++;
dp_table[end] = items[i][1];
} else {
int left = 0;
int right = end;
while (left < right) { // 在dp_table中查找第一个大于items[i][1]的数
int mid = left + (right - left) / 2;
if (items[i][1] > dp_table[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
dp_table[left] = items[i][1];
}
}
end++;
cout << end << endl;
return 0;
}
}
查看16道真题和解析