贪心算法-最优分解

最优分解问题

    问题描述:
          设 n 是一个正整数。现在要求将 n 分解为若干互不相同的自然数的和,且使这些自然数的乘积最大。如 10 = 3+7 =
          4+6 = 2+3+5 = ……
          最大乘积为:2 * 3 * 5 = 30
    问题分析:

           整数的一个性质:若 a + b =N(常数),则| a - b |越小, a * b 越大    

           证明 :
       
       
           当 n < 4 时, n 的分解的乘积小于 n ;
           当 n >= 4 时,n = 1 + ( n – 1 ) 因子的乘积也是小于 n ;
           所以 n = a + ( n – a ),2 ≤ a ≤ n - 2,可以保证乘积大于 n,即越分解乘积越大。                        
    算法设计:
           采用贪心策略:
                 将 n 分成从 2 开始的连续自然数的和。如果最后剩下一个数,将此数在后项优先的方式下均匀地分给前面各项。该  
           贪心策略首先保证了正整数所分解出的因子之差的绝对值最小,即 | a – b |最小;同时又可以将其分解成尽可能多的因
          子,且因子的值较大,确保最终所分解的自然数的乘积可以取得最大值 

                对剩下的一个数均匀分给前面的各项时,进行优化,对最后一个数除以前面项的个数,得到的整数最为一个基数,

            给前面的每一项都加这个基数,然后对最后一个数对前面的项数取余,从后向前,每一项加1,直到余数为0,不在加

    算法代码:
// ####################################################
//            贪心算法解决 '整数最优分解' 问题.               
// ####################################################

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STR_LEN 100
#define TRUE    1
#define FALSE   0

int DoIntOptDecomposition( int n, int *a );

//分解整数,并且计算乘积 
int DoIntOptDecomposition( int n, int *a )
{
  int MaxProduct = 1; // 乘积
  int k = 1;
  int count = 2;			// 从 '2' 开始处理 
	
	//将 'n' 分成连续的自然数 
	while((n - count) > 0)
	{
		n -= count;
		a[k++] = count++;
	}
	//设置'a'数组的结束标记 
	a[k--] = -1;
	
	//将最后剩下的一个数,以后项优先的方式均匀分给前面各项 
	int basicsNum = n / (k - 1);		//前面项平均分配到的最低数量 
	int surplusNum = n % (k - 1); 	    //剩余多的,分配给后项,每项分 '1' 
	while(k > 0) 
	{
		a[k] += basicsNum;
		if( surplusNum > 0 )
		{
			a[ k ] += 1;
			surplusNum --;	
		} 
		k --;
	}
	
	//计算乘积 
	//k此时值为 '0',所有自增 '1' 
	while(k++, a[k] > 0)
	{
		MaxProduct *= a[k];
	}

  return MaxProduct;
}

int main( void )
{
  char StrN[ STR_LEN ];
  int  *a, *p;
  int  n, MaxProduct;
  int  IsStop;

  IsStop = FALSE;
  while ( !IsStop )
  {
  	system( "cls" );

		// 输入字符串 'A' ...
  	printf( "\n\n\t请输入 < 待分解的整数 > , 输入 < q / Q > 表示结束 : " );
    scanf( "%s", StrN );
    if ( strlen( StrN ) > 0 )
		  IsStop = ( ( StrN[ 0 ] == 'q' ) || ( StrN[ 0 ] == 'Q' ) );
    else
      printf( "\t输入的整数不能为空 !\n\n" );

		if ( !IsStop )
		{
      a = ( int * )malloc( STR_LEN * sizeof( int ) );

	  	// 得到输入的整数值 ...
		  n = atoi( StrN );

      // 整数最优分解 ...
      MaxProduct = DoIntOptDecomposition( n, a );

	  	// 显示计算结果 ...
      printf( "\n\t< 整数最优分解乘积为:%d > \n", MaxProduct );

	  	printf( "\n\t< 分解因子值为 > \n" );
			int i = 1;
			while(a[i] > 0)
			{
				printf("\t%d", a[i]);
				i++;
			}
		
    	free( a );

    	printf( "\n\n" );
     	system( "PAUSE" );
		}
  }
  printf( "\n\n" );
  system( "PAUSE" );
  
  return 0;
}
    测试结果:

    

  • 6
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值