• 低价购买(LIS方案统计)


    题意:https://www.luogu.com.cn/problem/P1108

    如果两个数列组成的数字完全相同,那我们说这两个数列相同。

    求出最长下降子序列的方案数。


    题解来自 wjyyy大神。

    dp过程中,f数组存的是最长下降子序列的长度,ff数组的下标i是以i结尾的意思,所以最长下降子序列(除了最后一位外)的数据已经丢失,因此不能在方案数相加时再判断是否能加。

    我们从头来看,

    1. 如果一个数列的第一个数与另一个数列的第一个数相同,那么现在可以判断它们相等,即可以把其中一个删掉(在代码中的处理是t [ j ] =0)。当不同的数接在它的后面时,又可以将它们判断为两个数列,这是不互相影响的。因为两个数列都可以由这个相等的数列转移而来
    2. 如果一个数列的第一个数与另一个数列的第一个数不同,那么它们不等,且无论后面添加什么,都不相等,即不删去,则按照普通的判断继续做。

    由上面的两点,我们已经把重复的删掉,这样可以防止重复计数。

    #include <bits/stdc++.h>
    using namespace std;
    #define max(a,b)    (a>b?a:b)
    int a[5009],f[5009],t[5009];
    //a[i]是题目给的股票价格,f[i]是第i天最长的长度
    //t[i]是以i结尾的方案
    int main()
    {
        int n,maxn=0;
        cin>>n;
        for(int i=1;i<=n;i++)    cin>>a[i],f[i]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                if(a[i]<a[j])
                    f[i]=max(f[i],f[j]+1);
            }//目前是正常求最长下降子序列 
            maxn=max(maxn,f[i]);//记下最长的长度 
            for(int j=1;j<i;j++)
            {
                if(f[i]==f[j]&&a[i]==a[j])//一样长而且数列完全一样 
                    t[j]=0;
                else if(f[i]==f[j]+1&&a[i]<a[j])//可以接上前面的
                    t[i]+=t[j]; 
            }
            if(!t[i])    t[i]=1;//为了后面的数转移 
        }    
        int ans=0;
        for(int i=1;i<=n;i++)
            if(f[i]==maxn)    ans+=t[i];
        cout<<maxn<<" "<<ans;
    } 
  • 相关阅读:
    zmodem协议的使用(SecureCRT)
    Centos6.5下安装php
    CentOS6.5下Mysql数据库的安装与配置
    YUM更换源--yum找不到安装包(转)
    百度Ueditor编辑器的Html模式自动替换样式的解决方法
    TextArea里Placeholder换行问题
    tp可用的超强第三方图表类库-JpGraph
    确保 PHP 应用程序的安全
    在线网站速度测试
    几款整站抓取的工具
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12501951.html
Copyright © 2020-2023  润新知