解题思路
-
题目要求:
- 马戏团员需要叠罗汉表演
- 上面的人必须比下面的人矮且轻(或相等)
- 求最大能叠多高
- 需要处理多组输入
-
解题策略:
- 先按体重从小到大排序(相同体重时身高高的排前面)
- 然后对身高求最长递增子序列
- 使用二分查找优化LIS算法
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Person {
int id, weight, height;
};
// 按体重排序,体重相同时身高高的排前面
bool compare(const Person& a, const Person& b) {
if(a.weight != b.weight) return a.weight < b.weight;
return a.height > b.height;
}
// 二分查找第一个大于x的位置
int binarySearch(vector<int>& arr, int len, int x) {
int left = 0, right = len - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if(arr[mid] <= x) left = mid + 1;
else right = mid - 1;
}
return left;
}
// 求最长递增子序列
int getLIS(vector<Person>& people) {
if(people.empty()) return 0;
vector<int> dp;
dp.push_back(people[0].height);
for(int i = 1; i < people.size(); i++) {
if(people[i].height >= dp.back()) {
dp.push_back(people[i].height);
} else {
int pos = binarySearch(dp, dp.size(), people[i].height);
dp[pos] = people[i].height;
}
}
return dp.size();
}
int main() {
int n;
while(cin >> n) { // 处理多组输入
vector<Person> people(n);
// 读取输入
for(int i = 0; i < n; i++) {
cin >> people[i].id >> people[i].weight >> people[i].height;
}
// 按体重排序
sort(people.begin(), people.end(), compare);
// 计算最大高度
cout << getLIS(people) << endl;
}
return 0;
}
import java.util.*;
public class Main {
static class Person {
int id, weight, height;
Person(int id, int weight, int height) {
this.id = id;
this.weight = weight;
this.height = height;
}
}
// 二分查找第一个大于x的位置
static int binarySearch(int[] arr, int len, int x) {
int left = 0, right = len - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if(arr[mid] <= x) left = mid + 1;
else right = mid - 1;
}
return left;
}
// 求最长递增子序列
static int getLIS(Person[] people) {
if(people.length == 0) return 0;
int[] dp = new int[people.length];
int len = 0;
dp[len++] = people[0].height;
for(int i = 1; i < people.length; i++) {
if(people[i].height >= dp[len-1]) {
dp[len++] = people[i].height;
} else {
int pos = binarySearch(dp, len, people[i].height);
dp[pos] = people[i].height;
}
}
return len;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) { // 处理多组输入
int n = sc.nextInt();
Person[] people = new Person[n];
// 读取输入
for(int i = 0; i < n; i++) {
people[i] = new Person(sc.nextInt(), sc.nextInt(), sc.nextInt());
}
// 按体重排序
Arrays.sort(people, (a, b) -> {
if(a.weight != b.weight) return a.weight - b.weight;
return b.height - a.height;
});
// 计算最大高度
System.out.println(getLIS(people));
}
}
}
class Person:
def __init__(self, id, weight, height):
self.id = id
self.weight = weight
self.height = height
def binary_search(arr, length, x):
left, right = 0, length - 1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] <= x:
left = mid + 1
else:
right = mid - 1
return left
def get_lis(people):
if not people:
return 0
dp = [people[0].height]
for i in range(1, len(people)):
if people[i].height >= dp[-1]:
dp.append(people[i].height)
else:
pos = binary_search(dp, len(dp), people[i].height)
dp[pos] = people[i].height
return len(dp)
# 处理多组输入
while True:
try:
n = int(input())
people = []
# 读取输入
for _ in range(n):
id, weight, height = map(int, input().split())
people.append(Person(id, weight, height))
# 按体重排序,体重相同时身高高的排前面
people.sort(key=lambda x: (x.weight, -x.height))
# 计算最大高度
print(get_lis(people))
except EOFError:
break
算法及复杂度
- 算法:排序 + 二分查找优化的最长递增子序列
- 时间复杂度:
- 排序和LIS各需要
- 空间复杂度:
- 需要存储dp数组