CSUOJ 1560 图书管理员的表白方式

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...

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
#include
#include
#include
using namespace std;
typedef long long ll;
int cal_1[110],cal_2[110];
int Dp(int a[], int len)
{
	int dp[110] = { 0 };
	int cnt = 1;
	for (int i = 0; i < len; i++)
	{
		dp[i] = 1;
		for (int j = 0; j < i; j++)
		{
			if (a[i]>a[j])
				dp[i] = max(dp[i], dp[j]+1);
			cnt = max(cnt, dp[i]);
		}
	}
	return cnt;
}
int main()
{
	int T;
	while (~scanf("%d", &T))
	{
		while (T--)
		{
			int flag = 0;
			int m;
			scanf("%d", &m);
			for (int i = 0; i < m; i++)
			{
				scanf("%d", &cal_1[i]);
				cal_2[m - i - 1] = cal_1[i];
			}
			int cnt=-1;
			for (int i = 1; i < m-1; i++)
			{
				int down = Dp(cal_2 + m - i - 1, i + 1);//正向
				int up = Dp(cal_1 + i, m - i);//反向
				if (down == 1 || up == 1)//只有一本时无法构成V型
					continue;
				cnt = max(cnt, down + up - 1);
			}
			if (cnt == -1)
				cout << "SAD" << endl;
			else
				cout << "HAPPY" << endl << m-cnt << endl;
		}
	}
	return 0;
}
/**********************************************************************
	Problem: 1560
	User: leo6033
	Language: C++
	Result: AC
	Time:68 ms
	Memory:2024 kb
**********************************************************************/

你可能感兴趣的:(CSUOJ 1560 图书管理员的表白方式)