题目
很多肥老鼠认为,长的越肥,奔跑速度就越快,为了反驳这个观点,你现在需要对老鼠的体重和速度进行研究,你要在老鼠序列中找出一个子序列,使得老鼠的体重在增加,但是速度却在减慢
输入
输入以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 晨
时旭日东升鸟啭莺啼