zoukankan      html  css  js  c++  java
  • poj1952 BUY LOW, BUY LOWER[线性DP(统计不重复LIS方案)]

    如题。$N leqslant 5000$。


    感觉自己思路永远都是弯弯绕绕的。。即使会做也会被做繁掉。。果然还是我太菜了。


    递减不爽,先倒序输入算了。第一问做个LIS没什么说的。第二问统计个数,考虑什么时候是重复计算的。$g[i]$表示第$i$个数结尾的LIS长度的方案(不重复)。当统计时dp到一个数时显然从前面满足$f_j+1=f_i且A_j<A_i$条件的累加过来,$A_j$不同的时候,自然不会有重复;当有相同的数且f一样时,如果这几种都加入,就重复了。而相同的几个数字显然靠后的方案统计到的更多,所以每次只取最靠右的那个数累加上去即可。实现上,开一个桶,记录vis,结束后再吐出来。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<queue>
     7 #define dbg(x) cerr<<#x<<" = "<<x<<endl
     8 #define _dbg(x,y) cerr<<#x<<" = "<<x<<"   "<<#y<<" = "<<y<<endl
     9 using namespace std;
    10 typedef long long ll;
    11 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
    12 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
    13 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    14 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    15 template<typename T>inline T read(T&x){
    16     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    17     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    18 }
    19 const int N=5000+7,M=1<<17,INF=0x3f3f3f3f;
    20 int f[N],g[N],lis[N],a[N],vis[M],bin[N];
    21 int n,len,ans,tot,cnt;
    22 
    23 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
    24     read(n);for(register int i=1;i<=n;++i)read(a[n-i+1]);
    25     lis[len=1]=INF;
    26     for(register int i=1;i<=n;++i){
    27         f[i]=lower_bound(lis+1,lis+len+1,a[i])-lis;
    28         if(f[i]>len)lis[++len]=a[i];else lis[f[i]]=a[i];
    29         MAX(ans,f[i]);
    30     }
    31     for(register int i=1;i<=n;++i){
    32         if(f[i]==1){g[i]=1;continue;}
    33         for(register int j=i-1;j;--j)if(!vis[a[j]]&&a[j]<a[i]&&f[j]+1==f[i])vis[bin[++tot]=a[j]]=1,g[i]+=g[j];
    34         while(tot)vis[bin[tot--]]=0;
    35     }
    36     for(register int i=n;i;--i) if(!vis[a[i]]&&f[i]==ans)cnt+=g[i],vis[a[i]]=1;
    37     printf("%d %d
    ",ans,cnt);
    38     return 0;
    39 }
    View Code

    嗯这个是本人极其繁琐的想法。发现自己傻了有没有。。而且数据大的话桶不就挂了吗。。所以依据原来思路,改变对于dp状态的定义。$g[i]$表示第$i$个数结尾的长度为LIS的方案数,且不包括之前所有和自己相同且$len_{LIS}$相同的数的方案。这样每次转移时遇到相同即break。保证取的决策一定来源于上一个相同数和现在这个数之间。具体还是看code吧。。

    另外还有一种做法是网络流。。不想写了QwQ。  ←不行,建边都会建炸掉

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<queue>
     7 #define dbg(x) cerr<<#x<<" = "<<x<<endl
     8 #define _dbg(x,y) cerr<<#x<<" = "<<x<<"   "<<#y<<" = "<<y<<endl
     9 using namespace std;
    10 typedef long long ll;
    11 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
    12 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
    13 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    14 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    15 template<typename T>inline T read(T&x){
    16     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    17     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    18 }
    19 const int N=5000+7,M=1<<17,INF=0x3f3f3f3f;
    20 int f[N],g[N],lis[N],a[N];
    21 int n,len,ans,tot,cnt;
    22 
    23 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
    24     read(n);for(register int i=1;i<=n;++i)read(a[n-i+1]);
    25     lis[len=1]=INF;
    26     for(register int i=1;i<=n;++i){
    27         f[i]=lower_bound(lis+1,lis+len+1,a[i])-lis;
    28         if(f[i]>len)lis[++len]=a[i];else lis[f[i]]=a[i];
    29         MAX(ans,f[i]);
    30     }
    31     g[0]=1;
    32     for(register int i=1;i<=n;++i){
    33         for(register int j=i-1;~j;--j){
    34             if(a[i]==a[j]&&f[i]==f[j])break;
    35             if(f[i]==f[j]+1&&a[j]<a[i])g[i]+=g[j];
    36         }
    37     }
    38     for(register int i=1;i<=n;++i)if(f[i]==ans)cnt+=g[i];
    39     printf("%d %d
    ",ans,cnt);
    40     return 0;
    41 }
  • 相关阅读:
    实验十四 团队项目评审&个人学习总结
    实验四 附加实验项目互评
    201671010401 包稚潼+《英文文本统计分析》结队项目报告
    201671010401包稚潼 实验二 词频统计软件项目报告
    201671010401包稚潼 实验三作业互评与改进
    阅读《构建之法》提出的相关问题
    201671010404+陈润菊 实验十四 团队项目评审课程&学习总结
    201671010404+陈润菊 实验四 附加作业-项目互评
    201671010404+陈润菊 实验四《英文文本统计分析》结对项目报告
    201671010404+陈润菊 实验二软件工程项目
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10720428.html
Copyright © 2011-2022 走看看