HDU1160 FatMouse's Speed(最长上升子串)

题目链接:http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=3&sectionid=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);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值