九度oj-合唱队形
2018-04-06 10:44
141 查看
转载自:这位博主~
题目:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
[b]输入描述:[/b]输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。
[b]输出描述:[/b]可能包括多组测试数据,对于每组数据,输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
示例1
动态规划博大精深!!首先这又是个求最长递增序列的问题,我们可以把问题分成两部分,首先是从起点到当前点递增,然后是当前点到末尾点递减。然后分别求出两部分的最长序列个数,结果就是总长度减去这两部分的和(其中注意当前点被计算了两次)。其中计算从当前点到末位点递减序列时,要利用末位点到当前点递增这个等价的条件,因为此时末尾点的状态在当前点的状态之前。注意求解过程中,思路一定要清晰!# include<stdio.h>
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int n,i,j;
int dp2[1000];
int a[1000];
int dp1[1000];
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++)
{
int tmp1=1;
for(j=0;j<i;j++)
{
if(a[j]<a[i])
tmp1=max(tmp1,dp1[j]+1);
}
dp1[i]=tmp1;
}
/* for(i=0;i<n;i++)
printf("%d ",dp1[i]);
printf("\n");*/
//找到以i开头的最长递减子序列
//等价于以i结尾的反向增序列
for(i=n-1;i>=0;i--)
{
int tmp2=1;
for(j=n-1;j>i;j--)
{
if(a[j]<a[i])
tmp2=max(tmp2,dp2[j]+1);
}
dp2[i]=tmp2;
}
/* for(i=0;i<n;i++)
printf("%d ",dp2[i]);
printf("\n");*/
//判断两者的和
int ans=1;
for(i=0;i<n;i++)
{
if(ans<dp1[i]+dp2[i]-1)
ans=dp1[i]+dp2[i]-1;//dp[i]计算了两遍
}
printf("%d\n",n-ans);
}
return 0;
}
题目:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
[b]输入描述:[/b]输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。
[b]输出描述:[/b]可能包括多组测试数据,对于每组数据,输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
示例1
输入:
8 186 186 150 200 160 130 197 220
输出:
4解题思路:
动态规划博大精深!!首先这又是个求最长递增序列的问题,我们可以把问题分成两部分,首先是从起点到当前点递增,然后是当前点到末尾点递减。然后分别求出两部分的最长序列个数,结果就是总长度减去这两部分的和(其中注意当前点被计算了两次)。其中计算从当前点到末位点递减序列时,要利用末位点到当前点递增这个等价的条件,因为此时末尾点的状态在当前点的状态之前。注意求解过程中,思路一定要清晰!# include<stdio.h>
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int n,i,j;
int dp2[1000];
int a[1000];
int dp1[1000];
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++)
{
int tmp1=1;
for(j=0;j<i;j++)
{
if(a[j]<a[i])
tmp1=max(tmp1,dp1[j]+1);
}
dp1[i]=tmp1;
}
/* for(i=0;i<n;i++)
printf("%d ",dp1[i]);
printf("\n");*/
//找到以i开头的最长递减子序列
//等价于以i结尾的反向增序列
for(i=n-1;i>=0;i--)
{
int tmp2=1;
for(j=n-1;j>i;j--)
{
if(a[j]<a[i])
tmp2=max(tmp2,dp2[j]+1);
}
dp2[i]=tmp2;
}
/* for(i=0;i<n;i++)
printf("%d ",dp2[i]);
printf("\n");*/
//判断两者的和
int ans=1;
for(i=0;i<n;i++)
{
if(ans<dp1[i]+dp2[i]-1)
ans=dp1[i]+dp2[i]-1;//dp[i]计算了两遍
}
printf("%d\n",n-ans);
}
return 0;
}
相关文章推荐
- 九度OJ 题目1131:合唱队形
- [ACM] 九度OJ 合唱队形 (最长递增子序列改版)
- 九度OJ 1131:合唱队形 (DP、最长上升下降序列)
- 九度OJ 1131:合唱队形 (DP、最长上升下降序列)
- 九度OJ 1131 合唱队形 (动态规划DP)
- 动态规划试题:合唱队形
- NOIP 合唱队形 (LIS应用)
- Vijos P1098 合唱队形(动态规划,双重LIS)
- 【NOIP2004】合唱队形
- 29:合唱队形
- [期望] UOJ #214. 【UNR #1】合唱队形
- codevs1058 luogu1091 合唱队形
- luogu1091合唱队形
- RQNOJ 合唱队形(LIS最大上升序列解析)
- 【最长上升子序列】[NOIP2004提高组]合唱队形
- 合唱队形(LIS最长递增子序列) 解题过程
- poj 2711:合唱队形
- 合唱队形 九度1131 RONOJ26
- 九度OJ-1131-合唱队形
- 动态规划---合唱队形(LIS问题)