Loading

D. Mysterious Present

Link

如果不考虑card只考虑信封 那么先对所有信封排序(先按w从小到大排,如果w一样按h从小到大排)
然后就是对信封的h n²求最长上升子序列(同时要考虑到w可能相等) 考虑card 只有宽和高都大于w和h的才能进行转移
因此初始化时让dp[i]=1 if(a[i].w>W&&a[i].h>H)否则为0 且只有在dp[j]!=0时才能发生转移 发生转移时记录路径

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
 
const int N = 5005;
struct node
{
	int w,h,id;
}a[N];
bool cmp(node a,node b)
{
	if(a.w!=b.w) return a.w<b.w;
	else return a.h<b.h;
}
int dp[N],path[N],res[N];
int main()
{
	ios::sync_with_stdio(false);
 
	int n,W,H;
	cin>>n>>W>>H;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].w;
		cin>>a[i].h;
		a[i].id=i;
	}
	sort(a+1,a+1+n,cmp);
        //初始化
	for(int i=1;i<=n;i++)
	{
		if(a[i].w>W && a[i].h>H)
			dp[i] = 1;
	}
        //dp
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<i;j++)
		{
			if(dp[j]==0) continue;//这步很关键
			if(a[i].h>a[j].h&&a[i].w>a[j].w && dp[j]+1>dp[i])
			{
				dp[i] = dp[j]+1;
				path[i]=j; //j->i;
			}
		}
	}
	int ans=0,ind=0;//ind要初始化成0,否则在ans=0的情况下会出问题
	for(int i=1;i<=n;i++)
	{
		if(dp[i]>ans)
		{
			ans = dp[i];
			ind = i;
		}
	}
	cout<<ans<<endl;
	int cnt=0;
	while(ind!=0)
	{
		res[++cnt]=ind;
		ind = path[ind];
	}
	for(int i=cnt;i>=1;i--)
	{
		if(i==cnt) cout<<a[res[i]].id;
		else cout<<" "<<a[res[i]].id;
	}
}
posted @ 2021-03-05 15:17  金木换  阅读(73)  评论(0)    收藏  举报