1.最长不下降子序列
题目描述:
Description
A numeric sequence of ai is ordered if a1 < a2 < … <aN. Let the subsequence of the given numeric sequence (a1,a2, …,aN) be any sequence (ai1,ai2, …,aiK), where 1 <=i1 < i2 < … <iK <=N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
Input
The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000
Output
Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.
Sample Input
7
1 7 3 5 9 4 8
Sample Output
4
Code:
/*
Title : Longest Ordered Subsequence
Author : minisheep
Running time:47MS
Memory cost:224K
*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1001;
int a[maxn],m;
int dp[maxn];
int LIS()
{
int i,j,temp;
temp = 1;
for(i=1;i<=m;i++)
{
dp[i] = 1;
for(j=1;j<i;j++)
{
if(a[j]<a[i] && dp[j] + 1 > dp[i])
{
dp[i] = dp[j] + 1;
}
}
if(dp[i] > temp)
{
temp = dp[i];
}
}
return temp;
}
int main()
{
int i,cnt;
while(cin>>m)
{
for(i=1;i<=m;i++)
{
cin>>a[i];
}
cnt = LIS();
cout<<cnt<<endl;
}
}
2.抄近路,魔法石矿简单讲解
(1)抄近路
(2)魔法石矿
3.一个重要定理及相关题目(导弹拦截,楼兰宝藏)
(1)导弹拦截问题
(2)楼兰宝藏
4.和谐俱乐部(sgu199)
5.友好城市,合唱团
(1)
(2)合唱团
1)题目描述:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,
则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入:
输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。
第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。
输出:
可能包括多组测试数据,对于每组数据,
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
样例输入:
8
186 186 150 200 160 130 197 220
样例输出:
4
2)解法
动态规划:
d1表示以i结尾的左侧最长递增子序列长度
d2表示以i开头的右侧最长递减子序列长度
d1+d2中最大的情况是合唱队形的最优解,max中位置i计算了两次,所以长度为max-1
需要(n-max+1)位同学出列
3)代码
#include <stdio.h>
#include <stdlib.h>
int maxnum(int x,int y)
{
return x>y?x:y;
}
int main()
{
int n,i,j,a[101],dp1[101],dp2[101],max;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
dp1[i]=0;
dp2[i]=0;
}
//找出以i为结尾的最长递增子序列
for(i=0;i<n;i++)
{
dp1[i]=1;
for(j=0;j<i;j++)
if(a[i]>a[j])
dp1[i]=maxnum(dp1[i],dp1[j]+1);
}
//找出以i为开头的最长递减子序列(逆序即为递增)
for(i=n-1;i>=0;i--)
{
dp2[i]=1;
for(j=n-1;j>i;j--)
if(a[i]>a[j])
dp2[i]=maxnum(dp2[i],dp2[j]+1);
}
//判断以i为最高身高的最长满足序列长度(注意i在dp1和dp2中算了两遍,最后要减去)
max=1;
for(i=0;i<n;i++)
{
if(max<(dp1[i]+dp2[i]))
max=dp1[i]+dp2[i];
}
//总人数减去最长序列即为最少人数
printf("%d\n",n-max+1);
}
return 0;
}