一中OJ #1457 越大越聪明[Uva 10131 -> Is Bigger Smarter?] | 动态规划 字典序LIS | 解题报告

来源:互联网 发布:canvas2image.js 下载 编辑:程序博客网 时间:2024/05/16 07:40

一中OJ | #1457 Is Bigger Smarter?

时限 1000MS/Case 内存 64MB/Case





题目描述

一些人认为,大象的体形越大,脑子越聪明。为反驳这一错误观点,你想要分析一组大象的数据,找出尽量多的大象组成一个体重严格递增但IQ严格递减的序列。

输入格式

第一行一个整数N(编号为1..N)
接下来的N行,每行两个整数,分别第i头大象表示体重W[i]和IQ指数S[i]。

输出格式

第一行输出一个整数,表示找到的最长的大象序列长度M;
接下来M行,每行一个整数,表示找找的大象编号序列,如果有多个这样的序列,请输出字典序最小的。

样例输入

9
6008 1300
6000 2100
500 2000
1000 4000
1100 3000
6000 2000
8000 1400
6000 1200
2000 1900

样例输出

4

4

5

2

1

数据范围

输入数据保证1<=M<=1000
0<W[i],S[i]<=10000

----------------------------------------------------------

题目分析

这道题严格要求W严格递增的同时IQ严格递减,所以先把其中一个排序之后找另一个的严格连续(升降)子序列

问题就在于,要输出字典序最小的编号序列,这个编号还是输入顺序的编号

所以必须带着结构体找LIS/LDS

我的想法是设一个数组,d[i]表示以第i个编号的大象为开头的子序列的长度(不同于常规d[i]存的是以d[i]结尾的子序列长度)

然后搜完子序列长度之后,得到子序列长度ans,输出ans

遍历d[i],当d[i]==ans时,输出i,记录当前的i为NEXT,然后将i归零

下一次当d[i]==ans-1时,如果第NEXT头大象与第i头大象之间有严格不等关系,就输出i,然后循环直到ans扣完就是最小字典序LIS啦

对于生成d[i]数组是可以用二分的,可是我懒得去倒转来写那么多,反正1000^2也不怕超时嘛= =

----------------------------------------------------------

代码

#include <iostream>#include <algorithm>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <set>#include <queue>#include <stack>#include <vector>#include <map>#define hashsize 1000003#define inf 0x7f7f7f7fusing namespace std;struct node{int id;int w;int iq;friend bool operator <(node a,node b)//严格大于 && 严格小于 {if(a.w<b.w && a.iq>b.iq) return true;return false;}friend bool operator >(node a,node b){if(a.w>b.w && a.iq<b.iq) return true;return false;}}f[1005];int dp[1005],did[1005]/*did[id]为以第id个元素开头的LIS长度*/,ans=0,n,NEXT=0,p;bool _cmp(node a,node b){return a.iq>b.iq;}bool cmpid(node a,node b){return a.id<b.id;}int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d%d",&f[i].w,&f[i].iq);f[i].id=i;}sort(f+1,f+1+n,_cmp);for(int i=n;i>0;i--) //反向找f {dp[i]=1;for(int j=i+1;j<=n;j++){if(f[j]>f[i] && dp[j]+1>dp[i]){dp[i]=dp[j]+1;}}did[f[i].id]=dp[i];ans=max(ans,dp[i]);}printf("%d\n",ans);sort(f+1,f+1+n,cmpid);for(int i=1;i<=n && ans>0;i++){if(did[i]==ans && (f[i]>f[NEXT] || NEXT==0)){NEXT=i;printf("%d\n",i);ans--;i=0;}}return 0;}