Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2787735
  • 博文数量: 471
  • 博客积分: 7081
  • 博客等级: 少将
  • 技术积分: 5369
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-04 21:55
文章分类

全部博文(471)

文章存档

2014年(90)

2013年(69)

2012年(312)

分类: C/C++

2012-09-04 21:42:26

问题描述:

给定一个数组,记录一串数字,可正可负,现要求出其中最大的连续子段和。

用数组a[N]记录所要求的数组,用数组dp[N]来记录连续子段和的状态

通过分析,可以知道:

当dp[i-1]>0时,无论a[i]为何值,dp[i]=a[i-1]+a[i]

当dp[i-1]<0时,也就是dp[i]记录到一个a[i-1]是负的,可以把dp[i-1]变成负的,那么dp[i-1]记录的这一段应该截掉,应为无论后面的a[K]多大,加上个负数总不可能是最大的子段和,因此将dp[i]=a[i],重新开始记录。

点击(此处)折叠或打开

  1. #include
  2. #define N 15
  3. int a[N];

  4. int subMax(int a[],int n)
  5. {
  6.     int dp[N],max=0,i,l=0,r=0;
  7.     dp[0]=a[0];
  8.     for(i=1;i
  9.     {
  10.         if(dp[i-1]>0)
  11.         {
  12.             dp[i]=dp[i-1]+a[i];//只要前面的所有数的和是正数,我就放心加,然后再与max比较
  13.             r++;
  14.         }
  15.         else
  16.         {
  17.             dp[i]=a[i];//如果前面的和已经是负数就没必要比较啦,重新来过
  18.             l=i;
  19.             r=i;
  20.         }
  21.         
  22.         if(max
  23.             max=dp[i];
  24.     }
  25.     printf("%d %d\n",l,r);
  26.     return max;
  27. }

  28. int main()
  29. {
  30.     int i;
  31.     for(i=0;i
  32.     {
  33.         scanf("%d",&a[i]);
  34.     }
  35.     int maxSum=subMax(a,N);
  36.     printf("the max sum: %d\n",maxSum);
  37.     return 0;
  38. }


  39. /*
  40. 1 4 0 7 9 0 13 -16 -19 20 -24 0 27 28 29
  41. 12 14
  42. the max sum: 84
  43. Press any key to continue
  44. */

点击(此处)折叠或打开

  1. // 子数组的最大和
  2. int Sum(int* a, int n)
  3. {
  4.     int curSum = 0;
  5.     int maxSum = 0;
  6.     for (int i = 0; i < n; i++)
  7.     {
  8.         if (curSum + a[i] < 0)
  9.             curSum = 0;
  10.         else
  11.         {
  12.             curSum += a[i] ;
  13.             maxSum = max(maxSum, curSum);
  14.         }
  15.     }
  16.     return maxSum;
  17. }
最大积连续子序列问题
 
给定一个整型数足a,求出最大连续子段的乘积,比如 1, 2, -8, 12, 7则输出12 * 7 = 84
分析

与最大子段和类似,注意处理负数的情况,

对于最大积问题: 
由于负数的存在,我们不能简简单单只存一个当前最大值,我们还需要存当前最小值。这里可以先把两个数的情况剪枝掉,还有用个数记录全0,如果是全0,直接返回0,OK!

点击(此处)折叠或打开

  1. #include
  2. #define min(a,b) a
  3. #define max(a,b) a>b? a:b
  4. int a[100];

  5. // 子数组的最大和,要排除全为0和 -x 0
  6. //由于负数的存在,我们不能简简单单只存一个当前最大值,我们还需要存当前最小值。
  7. //这里有个bug,就是如果前全都是0也会输出1
  8. int maxProduct(int* a, int n)
  9. {
  10.     int maxProduct = 1; // max positive product at current position
  11.     int minProduct = 1; // min negative product at current position
  12.     int r = 1; // result, max multiplication totally

  13.     for (int i = 0; i < n; i++)
  14.     {
  15.         if (a[i] > 0)
  16.         {
  17.             maxProduct=((maxProduct==0)?1:maxProduct);
  18.             minProduct=((minProduct==0)?1:minProduct);
  19.             maxProduct *= a[i];
  20.             minProduct = min(minProduct * a[i], 1);
  21.         }
  22.         else if (a[i] == 0)//那么这段积就打回原型为1,后面不算它
  23.         {
  24.             maxProduct = 0;
  25.             minProduct = 0;
  26.             //maxProduct = 1;
  27.             //minProduct = 1;
  28.         }
  29.         else // a[i] < 0
  30.         {
  31.             maxProduct=((maxProduct==0)?1:maxProduct);
  32.             minProduct=((minProduct==0)?1:minProduct);
  33.             int temp = maxProduct;
  34.             maxProduct = max(minProduct * a[i], 1);
  35.             minProduct = temp * a[i];
  36.         }

  37.         r = max(r, maxProduct);
  38.     }

  39.     return r;
  40. }

  41. int main()
  42. {
  43.     int i,n;
  44.     scanf("%d",&n);
  45.     for(i=0;i
  46.     {
  47.         scanf("%d",&a[i]);
  48.     }
  49.     int maxSum=maxProduct(a,n);
  50.     printf("the maxProduct sum: %d\n",maxSum);
  51.     return 0;
  52. }
  53. /*
  54. 2
  55. 0 0
  56. the maxProduct sum: 1
  57. Press any key to continue
  58. 2
  59. -1 0
  60. the maxProduct sum: 1
  61. Press any key to continue

  62. 5
  63. 0 -1 -1 3 3
  64. the maxProduct sum: 9
  65. Press any key to continue


  66. */
最长公共子序列问题 

考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm-1”,并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。不难证明有以下性质:

(1) 如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,…,zk-2”是“a0,a1,…,am-2”和“b0,b1,…,bn-2”的一个最长公共子序列;

(2) 如果am-1!=bn-1,则若zk-1!=am-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列;

(3) 如果am-1!=bn-1,则若zk-1!=bn-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列。

这样,在找A和B的公共子序列时,如有am-1=bn-1,则进一步解决一个子问题,找“a0,a1,…,am-2”和“b0,b1,…,bm-2”的一个最长公共子序列;如果am-1!=bn-1,则要解决两个子问题,找出“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列和找出“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列,再取两者中较长者作为A和B的最长公共子序列。


点击(此处)折叠或打开

  1. #include
  2. #include
  3. #define M 5
  4. #define N 10
  5. #define max(a,b) a>b?a:b
  6. char A[M],B[N];
  7. int d[M+1][N+1];
  8. int getLCS(char *A,int m,char *B,int n)
  9. {
  10.     memset(d,0,sizeof(d));
  11.     for(int i=1;i<=m;i++)
  12.     {
  13.         for(int j=1;j<=n;j++)
  14.         {
  15.             if(A[i]==B[j])
  16.             {
  17.                 d[i][j]=d[i-1][j-1]+1;
  18.             }
  19.             else
  20.             {
  21.                 d[i][j]=max(d[i-1][j],d[i][j-1]);
  22.             }
  23.         }
  24.     }
  25.     return d[M][N];
  26. }
  27. int main()
  28. {

  29.     scanf("%s",&A);
  30.     scanf("%s",&B);
  31.     int len=getLCS(A,M,B,N);
  32.     printf("the lcs of A and B %d\n",len);

  33.     return 0;
  34. }

  35. /*
  36. abcdc
  37. bffcgbffcg
  38. the lcs of A and B 3
  39. Press any key to continue
  40. */

一,    最长递增子序列问题的描述

设L=是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=,其中k1

 以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j
如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),
把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;

如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。

dp数组记录着每个a[i]结尾的最长子序列长度,遍历一次dp 即可得到最长的子序列的长度

点击(此处)折叠或打开

  1. #include
  2. #include
  3. #define N 20
  4. int a[N];
  5. int longest(int a[],int n)
  6. {
  7.     int dp[N],i,t=0;
  8.     memset(dp,0,sizeof(dp));
  9.     dp[0]=1;
  10.     
  11.     for(i=1;i
  12.     {
  13.         dp[i]=1;
  14.         for(int j=i-1;j>=0;j--)
  15.         {
  16.             if(a[i]>a[j] && dp[i]
  17.                 dp[i]=dp[j]+1;
  18.         }
  19.         if(t
  20.             t=dp[i];
  21.     }
  22.     for(int k=0;k
  23.     {
  24.         printf("%d ",dp[k]);
  25.     }
  26.     printf("\n");
  27.     return t;
  28. }

  29. int main()
  30. {
  31.     int i,n;
  32.     while(scanf("%d",&n)!=EOF)
  33.     {
  34.         for(i=0;i
  35.         {
  36.             scanf("%d",&a[i]);
  37.         }
  38.     int maxlength=longest(a,n);
  39.     printf("the maxlength : %d\n",maxlength);
  40.     }
  41.     return 0;
  42. }
  43. /*
  44. 10
  45. 1 4 7 2 5 8 1 9 23 1
  46. 1 2 3 2 3 4 1 5 6 1
  47. the maxlength : 6
  48. */




阅读(2185) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~