您的位置:首页 > 其它

图书管理员的表白方式

2015-07-14 15:57 411 查看


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

HINT

枚举每一本书作为最低点时的情况,左右求最长上升子序列,

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[105],a[105],b[105];

int dpa(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,rl=1,ll=1;
for(int i=1;i<n-1;i++)
{
rl=dpa(a+i,n-i);
ll=dpa(b+n-1-i,i+1);
if(rl==1||ll==1) continue;
l=max(rl+ll-1,l);
}
if(l!=-1)printf("HAPPY\n%d\n",n-l);
else printf("SAD\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: