CSU 1560 图书管理员的表白方式(dp)

Description
小V是中南大学图书馆的图书管理员,每天要整理很多同学们还回来的书。久而久之,他认识了很多常来图书馆的同学,比如说小L。简而言之吧,就是小V喜欢上了小L,并且想在下一次她来还书的时候表白。
小V的创意还是不错的,他精心准备了各种材料,打算构成“L”,“O”,“V”,“E”四个字母,在小L来的时候悄悄组合起来给她看。但是意外来了:在小L来的时候,小V只准备好了“L”,“O”,和“E”,“V”还没有拼好!但是机智的小V立刻想到了一个办法:他可以随手把旁边别人还的书合在一起,并且抽掉其中一部分,令剩下的书的高度构成了一个“V”形。
那么问题来了:已知N本书的高度,在不改变他们的顺序的前提下,能不能得到小V想要的“V”,如果可以的话,最少去掉多少本书呢?
(组成“V”的前提:h1>h2...<hn,即整个高度必须先递减再递增)
Input

多组数据,第一行有一个整数T,表示有T组数据。(T<=100)
以下每组数据第一行有一个整数N,表示这一排书的数量。(1<=N<=100)
然后接下来一行是N个整数,h1,h2...hn分别代表每本书的高度。(1<=hi<=100)
Output
如果可以构成”V”,输出“HAPPY”,并在下一行输出所需拿掉的最少数量。
如果不能,输出“SAD”。
Sample Input

7
3
3 2 3
4
3 2 4 3
5
1 2 4 6 7
1
22
2
25 8
3
98 16 68
4
88 14 82 69

Sample Output

HAPPY
0
HAPPY
1
SAD
SAD
SAD
HAPPY
0
HAPPY
1

【题意】给出每本书的高度。求使其变成V型至少需要拿掉几本书。

【分析】求两端的最长递增子序列。dp。递推公式:

          dp[ i ]以序列中第i个元素结尾的最长上升子序列的长度

         那么状态转移方程为:if (a[i] > a[j]) dp[i] = max (dp[i], dp[j] + 1);

【代码】

#include<bits/stdc++.h>
using namespace std;

int dp[105],a[105],b[105];
 
/*求最长递增子序列*/
int ff(int a[],int n)
{
	int p=1;
	memset(dp,0,sizeof dp);
	dp[0]=1;
	for(int i=1;i<n;i++)
	{
		for(int j=0;j<i;j++)
		{
			if(a[i]>a[j])
				dp[i]=max(dp[i],dp[j]+1);
		}
	}
	for(int i=0;i<n;i++)
		p=max(p,dp[i]);
	return p;
}
main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int n;
		scanf("%d",&n);
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			b[n-1-i]=a[i];
		}
		int l=-1,r1=1,l1=1;
		for(int i=1;i<n-1;i++)
		{
			r1=ff(a+i,n-i);
			l1=ff(b+n-1-i,i+1);
			if(r1==1||l1==1) continue;
			l=max(r1+l1-1,l);
		}
		if(l!=-1)printf("HAPPY\n%d\n",n-l);
		else printf("SAD\n");
	}
}
代码段 小部件
[Dàimǎ duàn xiǎo bùjiàn]
Code section widget
 

猜你喜欢

转载自blog.csdn.net/qq_38735931/article/details/83510284