最长不下降子序列 输出方案数
对于最长不下降子序列的求解,朴素的解法是N^2的,也可以用单调队列优化,从而降时间复杂度为Nlog(n).
涉及到方案数的输出时,只需要降长度为1的最长XX子序列的方案数赋成1,其他的长度的方案数均由前一个长度的方案推出.
如下图所示:
首先用朴素的最长非降子序列的方法求出每一个在最优序列中的位置:
建立如下的表
值的大小: 68 69 54 64 68 64 70 67 78 62 98 87
在序列中的位置 3 4 1 2 3 2 3 2 2 2 1 1(这里的在序列中的位置即是指以这个数为起点的最长XX子序列的长度)
下面是对方案的判重,这列我们借助一个一维的辅助数组来帮助判重.
time[n+1].z[0]=1; time[n+1].z[1]=1; for (int i=n;i>0;i--) { panchong[0]=0;//用来帮助判重的辅助数组. for (int j=i+1;j<=n+1;j++) { bool boo=false; if (f[j]==f[i]-1&&a[j]<a[i]) { for (int k=1;k<=panchong[0];k++) if (panchong[k]==a[j]) {boo=true;break;} if (boo==false){panchong[++panchong[0]]=a[j];add(time[i].z,time[j].z,time[i].z);} } } }
下面给出输出方案数的程序:
题目是USACO的
Section 4.3 .1Buy Low, Buy Lower
(代码比较冗余,可去NOCOW上看较为标准的代码)
#include <cstdlib> #include <cstdio> #include <cstring> struct { int z[15]; }time[10000]; int panchong[10000]; int a[10000]; int f[10000]; void add(int a[15],int b[15],int c[15]) { int d[15]; memset(d,0,sizeof(d)); int len; if (a[0]>b[0]) len=a[0];else len=b[0]; for (int i=1;i<=len;i++) { d[i]+=(a[i]+b[i]); d[i+1]+=(d[i]/100000000); d[i]=d[i]%100000000; } d[0]=len+2; while (d[d[0]]==0&&d[0]>0) d[0]--; while (d[d[0]]>=100000000) { d[d[0]+1]=d[d[0]]/100000000; d[0]++;} memset(c,0,sizeof(c)); for (int i=0;i<=d[0];i++) c[i]=d[i]; } void print(int a[15]) { printf("%d",a[a[0]]); for (int i=a[0]-1;i>0;i--) { if (a[i]/10000000==0) printf("0"); if (a[i]/1000000==0) printf("0"); if (a[i]/100000==0) printf("0"); if (a[i]/10000==0) printf("0"); if (a[i]/1000==0) printf("0"); if (a[i]/100==0) printf("0"); if (a[i]/10==0) printf("0"); printf("%d",a[i]); } printf("\n"); } int main() { freopen("plane.in","r",stdin); freopen("plane.out","w",stdout); int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); a[n+1]=-1000000; f[n+1]=0; for (int i=n;i>0;i--) for (int j=i+1;j<=n+1;j++) { if (a[i]>a[j]&&f[i]<f[j]+1) f[i]=f[j]+1; } memset(time,0,sizeof(time)); time[n+1].z[0]=1; time[n+1].z[1]=1; for (int i=n;i>0;i--) { panchong[0]=0; for (int j=i+1;j<=n+1;j++) { bool boo=false; if (f[j]==f[i]-1&&a[j]<a[i]) { for (int k=1;k<=panchong[0];k++) if (panchong[k]==a[j]) {boo=true;break;} if (boo==false){panchong[++panchong[0]]=a[j];add(time[i].z,time[j].z,time[i].z);} } } } int maxx=0; for (int i=1;i<=n;i++) if (f[i]>maxx) {maxx=f[i];}; panchong[0]=0; int biao[15]; memset(biao,0,sizeof(biao)); for (int i=1;i<=n;i++) if (f[i]==maxx) { bool boo=false; for (int k=1;k<=panchong[0];k++) if (a[i]==panchong[k]) {boo=true;break;} if (boo==false) {panchong[++panchong[0]]=a[i];add(biao,time[i].z,biao);} } printf("%d ",maxx); print(biao); return 0; }
foreverzsz原创,转载请注明出处。
本文出处:http://www.cnblogs.com/foreverzsz/archive/2010/11/12/1875662.html