双元素LIS问题

Mysterious Present

(codeforces 4D)

题目镜像

题面翻译

给出一个限制\((w,h)\)\(n\) 个物品的二维信息\((w_i,h_i)\)

求物品二维都满足 \(w_i>w,h_i>h\) 的前提下的最长二维严格上升子序列以及其长度\((w_i>w_{i-1},h_i > h_{i-1}\) )

如果找不到任何一个物品满足条件 只需输出一行 0

解题报告

不难看出这道题就是一个最长上升子序列(LIS)问题的加强版

把原本的一维问题扩展到了二维,我们参考LIS的思想还是可以用DP完美解决这个加强版问题

首先,我们先来复习一下LIS的代码

for(int i=1;i<=n;i++)
{
    cin>>a[i];
    dp[i]=1;
}
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
    if(a[i]>a[j])
      dp[i]=max(dp[i],dp[j]+1);
int ans=0;
for(int i=1;i<=n;i++)
    ans=max(ans,dp[i]);

但我们仔细想一想就会发现,实际上这道题目前还不是严格的二维LIS

因为序列中的元素是可以互换顺序的

所以选出的一个序列是不符合子序列的定义的

既然我们要保证\(w_i>w_j\)\(h_i>h_j\)同时成立

但只有每一次迭代都是\(i>j\)时,我们才方便用DP进行

那我们不妨把\(w_i>w_j\)关联到\(i>j\)上,

那么,

$ dp_i $ = \(max\) {\(dp_i, dp_j+1\) | \(i>j\) -> \(w_i>w_j ,h_i>h_j\)}

\(w_i>w_j\)关联到\(i>j\)的过程我们可以用一个结构体的sort实现

这样以后,这个问题实际上就退化为一维LIS了

$ dp_i $ = \(max\) {\(dp_i, dp_j+1\) | \(w_i!=w_j ,h_i>h_j\)}

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=5050;
int n,w,h;
struct node{
	int w,h,id;
}a[N];
int tot,dp[N],pre[N],b[N];
bool cmp(node a,node b)
{
	return a.w<b.w;
}
int main()
{
	cin>>n>>w>>h;
	for(int i=1;i<=n;i++)
	{
		int wi,hi;
		cin>>wi>>hi;
		if(wi>w && hi>h)
		{
			node t;
			t.w=wi;t.h=hi;t.id=i;
			a[++tot]=t;
		}
	}
	sort(a+1,a+1+tot,cmp);
	for(int i=1;i<=tot;i++)
	{
		dp[i]=1;
		for(int j=1;j<i;j++)
			if(a[i].h>a[j].h && a[i].w!=a[j].w && dp[i]<dp[j]+1)
			{
				dp[i]=dp[j]+1;
				pre[i]=j;
			}
	}
	int ans=0,pos;
	for(int i=1;i<=tot;i++)
	if(dp[i]>ans)
	{
		ans=dp[i];
		pos=i;
	}
	int t=ans;
	while(pos!=0)
	{
		b[t]=a[pos].id;
		pos=pre[pos];
		t--;
	}
	cout<<ans<<endl;
	for(int i=1;i<=ans;i++)
	cout<<b[i]<<" ";
	return 0;
}
posted @ 2022-12-03 17:44  octal_zhihao  阅读(18)  评论(0编辑  收藏  举报