HDU 1160 FatMouse's Speeds 解题报告

题目

很多肥老鼠认为,长的越肥,奔跑速度就越快,为了反驳这个观点,你现在需要对老鼠的体重和速度进行研究,你要在老鼠序列中找出一个子序列,使得老鼠的体重在增加,但是速度却在减慢

输入

输入以eof结束。
输入中每行有两个正整数,分别表示老鼠的体重和速度,范围均在1到10000之间,输入数据最多有1000只老鼠。
某些老鼠可能有相同的体重,某些老鼠可能有相同的速度,某些老鼠可能体重和速度都相同。

输出

我们是要在原来的老鼠序列中,找到一个最长的子序列,使得这个子序列中老鼠的体重在严格增加,速度却在严格降低。
首先输出满足条件的最长的子序列的长度。
其次,输出一个最长子序列的方案,要求输出每个老鼠在输入时候的编号,每个编号占一行,任意一种正确的方法都会被判正确。

传送门

题意分析

啊,这题说的比较明显,考察的是LIS,但是这题难点在存储路径和有2个参数,一个是重量,一个是速度,但是聪明如你,肯定可以想到用结构体存标号,重量,速度,然后先对数据按照重量排序,在对速度求最长递减子序列就好啦。关于路径存储问题,可以用一个vector存,然后再应用LIS的过程把dp[i] = max (dp[i], dp[j] + 1) 改成更加具体的判断,因为要存储路径,在对第i个元素选择的时候,要看找到它的状态从前面哪一个传过来的,然后记录下路径就好啦。
AC代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#define INF 0x3f3f3f
using namespace std;
const int maxn = 1e3+11;
int dp[maxn];//dp[i]表示以第i个元素结尾的最长递减子数列数
struct p{
    int num,wt,vt;
}a[maxn];
bool cmp(p a,p b){
    if (a.wt == b.wt) return a.vt < b.vt;
    return a.wt < b.wt;
}
int main(){
    int wt,v,k = 1;
    vector<int> vt[maxn];
    while(cin >> wt >> v){
        a[k].num = k, a[k].wt = wt, a[k].vt = v;
        k ++;
    }
    sort(a+1,a+k,cmp);
    vt[1].push_back(1);
    dp[1] = 1;
    for (int i = 1; i < k; i ++) dp[i] = 1;
    for (int i = 2; i < k; i++){
        int stemp = -(INF), idex;
        for (int j = 1; j < i; j++){//贪心,dp[i]的状态从前面最大的状态转移过来,记录值和标号,方便记录路径
            if ((a[j].vt > a[i].vt) && (a[j].wt != a[i].wt)){
                if (stemp < dp[j]) {
                    stemp = dp[j];
                    idex = j;//记录
                }
            }
        }
        if (stemp == -(INF)){//没找到符合条件的
            dp[i] = 1;
            vt[i].push_back(a[i].num);
        }
        else {
            dp[i] = stemp + 1;//更新状态
            vt[i] = vt[idex];//更新路径
            vt[i].push_back(a[i].num);
        }
    }
    int maxi=1;
    for (int i = 1; i < k; i++){
        if (vt[i].size() > vt[maxi].size()) maxi = i;
    }
    cout << vt[maxi].size() <<endl;
    for (auto i = vt[maxi].begin(); i != vt[maxi].end(); i ++){
        cout << *i << endl;
    }
    return 0;
}

总体来说,用的复杂度是O(n^2),但是这题数据比较小,可以过,如果数据大一些,那就要用set优化成O(nlongn)。
有什么问题欢迎斧正。

2020/4/23 晨
时旭日东升鸟啭莺啼

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值