题目链接:http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=3§ionid=2&problemid=4
题目大意:按体重上升,速度下降排序后,提取符合条件的最长子序列,以证明体重越高,速度越慢
参考链接:https://blog.csdn.net/liyongfan152/article/details/52211996
解题思路:理解的很模糊,首先想到最长上升子串模型,难点在于记录原始位置。先按要求排序,我遍历数列中每一个元素,对于每一个元素的位置,找出这个位置前面的子串的最长子串大小和这个子串的尾部位置(尾部位置是为了引出子串前面的每个元素),直到结束。
由于需要进行路径的记录,所以需要一个数组来存储路径,这个处理是解此题的关键点,我们可以这样进行
处理:先定义一个标记数组vis[maxn],并对其进行初始化,vis[i]=i;如果一个数列他的 1 3 5 6 9 为它的
最长上升子序列,那么我们可以用vis数组这样处理,每次将vis[now]=pre,就像现在这种情况
vis[3]=1; vis[5]=3 ;vis[6]=5; vis[9]=6;
这样只要获得最长上升子序列的位置终点位置,就能获得所有的路径
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
public class Main {
public static class Mouse{
int pos, weight, speed;
}
public static void main(String[] args) {
List<Mouse> list = new ArrayList<Mouse>();
//记录每个位置的最长子序列
int[] dp = new int[1002];
/**
* 由于需要进行路径的记录,所以需要一个数组来存储路径,这个处理是解此题的关键点,我们可以这样进行
处理:先定义一个标记数组vis[maxn],并对其进行初始化,vis[i]=i;如果一个数列他的 1 3 5 6 9 为它的
最长上升子序列,那么我们可以用vis数组这样处理,每次将vis[now]=pre,就像现在这种情况
vis[3]=1; vis[5]=3 ;vis[6]=5; vis[9]=6;
这样只要获得最长上升子序列的位置终点位置,就能获得所有的路径
*/
int[] vis = new int[1002];
for (int i = 1; i < vis.length; i++) {
vis[i] = i;
}
int flag = 0;
Scanner in = new Scanner(System.in);
int n=0;
while (in.hasNext()) {
Mouse m = new Mouse();
m.pos = n++;
m.weight = in.nextInt();
//模拟文件结尾,输入0即可结束,忽略
if(m.weight==0) {
break;
}
m.speed = in.nextInt();
list.add(m);
}
//对list排序,按照weight升序,speed降序
Collections.sort(list, new Comparator<Mouse>() {
@Override
public int compare(Mouse o1, Mouse o2) {
if(o1.weight != o2.weight) {
return o2.weight - o1.weight;
}else {
if(o1.speed<o2.speed) {
return o1.speed - o2.speed;
}else {
return 0;
}
}
}
});
//记录最长子序列大小
int max = -1;
//记录vis的引线,vis记录
int top = 0;
for (int i = 1; i < list.size(); i++) {//每次以i为终点的子序列
int temp = 0;//记录临时最大长度
for (int j = 0; j < i; j++) {
if (list.get(i).weight<list.get(j).weight&&list.get(i).speed>list.get(j).speed) {
if(temp<dp[j]) {//更新temp值
temp = dp[j];
flag = list.get(j).pos;//标记这个最大位置
}
}
if(temp!=0) {
//flag起到连接i和j的纽带作用
vis[list.get(i).pos]=flag;
}
dp[i] = temp+1;
}
if(max<dp[i]) {//更新max的值
max = dp[i];
top = list.get(i).pos;
}
}
//输出最大长度
System.out.println(max);
while(top!=vis[top]) {
//由于数组从0开始
System.out.println(top+1);
top = vis[top];
}
//还剩下一个
System.out.println(top+1);
}
}