您的位置:首页 > 其它

ural 1078. Segments

2013-08-10 17:57 274 查看


翻译来自NOCOW


Discription

一条线上有许多节,每一节都给定了其两端的坐标。这些节都编了从1-N的号码(n<500).如果说一节是在另一节之中,当且仅当两节是不同的,且第一节是完全包含在第二节之内,而他们的两端不一致。编一个程序,找出包括在节中最长序列节的号码。在该序列中,每一节,除最后一节,都是在前一节之中。


[编辑]Input
Format

第一行包括一个整数N,以下有N行,每行上有两个整数,他们是相应节左和右两端的坐标,这些坐标是在(-10000,10000)之间的整数。假设所给定的节是按照他们输入位置编号的。


[编辑]Output
Format

第一行必须包括一个整数,等于所创立序列的节数,接下来的每一行必须包括该序列的节数,这些节数必须按照节的长度增加的顺序输出,从最小的开始,如果有一个以上的输出序列,随意输出一个。

分析:对线段的右端点从小到大排序。设dp[i]为以第i个线段结尾的包含在第i个线段的最大数量。则dp[i]=max(dp[j]) (0<=j<i)。

Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define eps 1e-7
#define LL long long
#define pb push_back
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=505;
struct node{
int l,r,id,len;
}seg[maxn],ans[maxn];

int pre[maxn],dp[maxn];
int n,tot;

bool cmp(node a,node b){
return a.r<b.r;
}

bool cmp1(node a,node b){
return a.len<b.len;
}

void get_ans(int cur){
ans[tot++]=seg[cur];
if(pre[cur]==-1) return ;
get_ans(pre[cur]);
}

int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) {
scanf("%d %d",&seg[i].l,&seg[i].r);
seg[i].id=i+1;
seg[i].len=seg[i].r-seg[i].l;
}
sort(seg,seg+n,cmp);
memset(dp,0,sizeof(dp));
memset(pre,-1,sizeof(pre));
dp[0]=1;
for(int i=1;i<n;i++){
//int cl=seg[i].l;
for(int j=0;j<i;j++){
if(seg[j].l>seg[i].l&&seg[j].r<seg[i].r&&dp[j]>dp[i]){
dp[i]=dp[j]; pre[i]=j;
}
}
dp[i]++;
}
int index,maxnum=0;
for(int i=0;i<n;i++){
if(dp[i]>maxnum){maxnum=dp[i];index=i;}
}
tot=0;
get_ans(index);
sort(ans,ans+tot,cmp1);
printf("%d\n",maxnum);
for(int i=0;i<tot-1;i++) printf("%d ",ans[i].id);
printf("%d\n",ans[tot-1].id);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: