zoukankan      html  css  js  c++  java
  • 最大递增和最大递减求法和方案计数比较异同分析

      1 /*最大递增和最大递减的分析
      2 两个其实是一个道理
      3 只是维护和边界需要修改一点
      4 在理解的过程中突然有个想法:那就是直接套用最大递增,只是把数列改为原来的反数列,然后边界取负无穷大,然后求
      5 这个反数列的最大递增数列就可以了,事实证明,这是可行的
      6 */
      7 
      8 /*最大递增子序列算法**/
      9 #include <iostream>
     10 using namespace std;
     11 int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n
     12 {
     13        int left=0,right=len,mid=(left+right)/2;
     14        while(left<=right)
     15        {
     16               if(n>a[mid]) left=mid+1;//维护最大
     17               else if(n<a[mid]) right=mid-1;
     18               else return mid;
     19               mid=(left+right)/2;
     20        }
     21        return left;
     22 }
     23 int main()
     24 {
     25        int n,a[100],c[100],i,j,len,b[100];//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标
     26        while(cin>>n)
     27        {
     28               for(i=0;i<n;i++)
     29                      cin>>a[i];
     30               b[0]=1;
     31               c[0]=-1;//边界
     32               c[1]=a[0];
     33               len=1;//此时只有c[1]求出来,最长递增子序列的长度为1.
     34               for(i=1;i<n;i++)
     35               {
     36                      j=find(c,len,a[i]);
     37                      c[j]=a[i];
     38                      if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1
     39                             len=j;//更新len
     40               }
     41               cout<<len<<endl;
     42        }
     43        return 0;
     44 }
     45 
     46 /*最大递减子序列算法,都差不多*/
     47 #include <iostream>
     48 using namespace std;
     49 int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n
     50 {
     51        int left=0,right=len,mid=(left+right)/2;
     52        while(left<=right)
     53        {
     54               if(n<a[mid]) left=mid+1;//维护和递增刚好相反
     55               else if(n>a[mid]) right=mid-1;
     56               else return mid;
     57               mid=(left+right)/2;
     58        }
     59        return left;
     60 }
     61 int main()
     62 {
     63        int n,a[100],c[100],i,j,len,b[100];//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标
     64        while(cin>>n)
     65        {
     66               for(i=0;i<n;i++)
     67                      cin>>a[i];
     68               b[0]=1;
     69               c[0]=0x3f3f3f3f;//边界保证递减
     70               c[1]=a[0];
     71               len=1;//此时只有c[1]求出来,最长递增子序列的长度为1.
     72               for(i=1;i<n;i++)
     73               {
     74                      j=find(c,len,a[i]);
     75                      c[j]=a[i];
     76                      if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1
     77                             len=j;//更新len
     78               }
     79               cout<<len<<endl;
     80        }
     81        return 0;
     82 }
     83 */
     84 /*最大递减计数问题*/
     85 #include<stdio.h>
     86 #include<string.h>
     87 #include<iostream>
     88 using namespace std;
     89 const int maxn=5555;
     90 int a[maxn],dp[maxn],f[maxn];
     91 int main()
     92 {
     93     int n,i,j;
     94     scanf("%d",&n);
     95     for( i=1;i<=n;i++)
     96     scanf("%d",&a[i]);
     97     for( i=1;i<=n;i++)
     98     {
     99         dp[i]=1;//每个一i结尾的最下都是1
    100         f[i]=1;//初始化为最大方案,有n个
    101     }
    102     for( i=1;i<=n;i++)
    103     for( j=i+1;j<=n;j++)
    104     if(a[i]>a[j])
    105     {
    106         if(dp[j]<dp[i]+1)//继续增加长度
    107         {
    108             dp[j]=dp[i]+1;
    109             f[j]=f[i];//这条路还没走完
    110         }
    111         else if(dp[j]==dp[i]+1)//说明到这个点有多条路
    112         f[j]+=f[i];
    113     }
    114     else
    115     if(a[i]==a[j])//重复了,直接忽略这个点,将到这个点的方案数目置为0
    116     f[j]=0;
    117 //    for(int i=1;i<=n;i++)
    118 //    printf("%d %d %d
    ",i,dp[i],f[i]);
    119     int max=0,answer=0;
    120     for( i=1;i<=n;i++)
    121     if(max<dp[i])
    122        max=dp[i];
    123     for( i=1;i<=n;i++)
    124     if(max==dp[i])
    125     answer+=f[i];
    126     printf("%d %d
    ",max,answer);
    127     return 0;
    128 }
    129 
    130 /*最大递增计数问题
    131  嗯!借用开头的结论,将原来的数列取反,然后求递减数列的方案数目*/
    132 
    133 /*总结:其实最大递增和最大递减就是同一个道理,相互是对方的反面*/
  • 相关阅读:
    左耳听风-ARTS-第4周(2019/4/21-2019/4/27)
    Java集合总结
    Zuul网关总结
    左耳听风-ARTS-第3周(2019/4/7-2019/4/13)
    左耳听风-ARTS-第2周(2019/3/31-2019/4/6)
    Java泛型相关总结(下)
    左耳听风-ARTS-第1周
    去长江边走走,看看
    第1记
    c#发送邮件
  • 原文地址:https://www.cnblogs.com/okboy/p/3224186.html
Copyright © 2011-2022 走看看