2.8总结

此题,如果以某同学(t[i])作为最中间的那个人,如果要使此时能留下的人最多,那么我们就要找出其左边最长的增序列和右边的减序列,那么对于t[i],如何在其左边筛选出最长的增序列呢?

用l[i]记录以f[i]为t[i]时,递增的身高个数,首先,如果i=1,那么l[1]必然为1,再看l[2],如果f[2]>f[1],那么此时l[2]=2,否则l[2]=1,所以很容易得出规律,对于一个f[i],如果左边有数字比它小,以这个数字为t[i]时递增个数num,l[i]可以为numm+1,遍历其左边数字,便可以得到最大值。同理右边也是。最后留下来的人数为l[i]+r[i]-1;我们让每个f[i]当一次t[i],找出最后留下来人数最大值即可。

#include<stdio.h>
int f[105],n,l[105],r[105];
int main()
{
    int max=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        l[i]=1;
        r[i]=1;
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&f[i]);
    }
    for(int i=2;i<=n;i++)
    {
        for(int j=i-1;j>=1;j--)
        {
            if(f[i]>f[j]&&l[i]<=l[j]) l[i]=l[j]+1;
        }
    }
    for(int i=n-1;i>=1;i--)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(f[i]>f[j]&&r[i]<=r[j]) r[i]=r[j]+1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        //printf("%d %d\n",l[i],r[i]);
        if(max<r[i]+l[i]-1) max=r[i]+l[i]-1;
    }
    printf("%d",n-max);
    return 0;
}

用f[i][j]表示用前i种花填满j个花盆的方式,对于第i种花有x朵,如果我们取k朵,那么剩下j-k个花盆,我们还需要用前i-1种花填满这些花盆,所以有f[i-1][j-k]种方式,对于第i种花我们可以取的数量不能超过j和a[i],将所有能取的方式加起来,就是f[i][j];

#include<stdio.h>
int main()
{
    int n,m;
    int f[105][105]={0},a[106];
    scanf("%d %d",&n,&m);
    f[0][0]=1;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            for(int k=0;k<=j&&k<=a[i];k++)
            {
                f[i][j]+=f[i-1][j-k];
                f[i][j]=f[i][j]%1000007;
            }
        }
    }
    printf("%d",f[n][m]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值