文章图片
最近刚学了一下算法,看见有一个求最大k乘积的问题,这个问题可用动态规划来解决.具体解释如下:
/*
* ===========================================================================
*
*Filename:max_k_product.c
*
*Description:动态规划之最大k乘积问题
*
*Version:1.0
*Created:2013年11月21日 14时16分36秒
*Revision:none
*Compiler:gcc
*CopyRight: open , free , share
*Author:yexingkong(zhangbaoqing)
*Email: abqyexingkong@gmail.com
*Company:Xi'an University of post and Telecommunications
*
* ===========================================================================
*/#include
#include
#include
#include #include #defineARRAY_SIZE11/*定义数组大小 *//*1.问题描述:
* 设I是一个n位十进制整数,如果将I划分为k段,则可得到k个整数,这k个整数
* 的乘积称为I的一个K乘积,试设计一个算法,对于给定的I和K,求出I的最大乘积
*
*2.实现要求:
*2.1: 对于给定的I和K,设计I的最大k乘积.
*2.2: 由文件input.txt提供输入数据。文件的第1行中有2两个正整数n和k.正
*整数 n是序列的长度,正整数k是分割的段数。在接下来的一行中是一个
*n位十进制整数(n <= 10)
*2.3: 将结果输出到文件output.txt。文件第一行中的舒适计算出来的最大K
*乘积.
*
*
* 3.算法分析与设计:
*3.1:求I的k段最大乘积,可理解为在n位数中插入k-1个乘号,且使得各个整
*数乘积最大
*3.2: 要使k个数的乘积最大,则要使前k-1个数的乘积最大,同理,也要使前
*k-2个数的乘积最大,这说明此问题具有最优子结构和子问题重叠性,
*故可用动态规划方法来解。。
*3.3: k_max(i,k)表示第1 ~ i位数中插入k个乘号所得的最大值,a[i,j]表示
*第i~j位所组成的自然数.
*3.4: 现在假设将I分成K段后的最大乘积位K_max(n,k),且最后一组数为a(i,n),
*,可得状态转移方程: k_max(i,k) = max( k_max(j,k-1) * a(j+1,i)).
*
* *//* -------------------------------------------------------------------*/
/**
* @Synopsis=WriteFile用来随机生成长度为n的正整数I,并将其存入文件
*
* @Returns= 用来验证函数是否正确执行
*/
/* ----------------------------------------------------------------------------*/
int WriteFile()
{
int i,m=0;
int n = 0, k = 0;
int df[ARRAY_SIZE];
FILE*fp;
fp = fopen("input.txt","w");
if (NULL == fp)
{
perror("fopen");
exit(1);
}srand((unsigned)time(NULL));
n = 9.0 * rand() / (RAND_MAX + 1.0) + 1;
//整数I的长度(1<= n <= 10)k = 1.0 * (n-1) * rand()/ (RAND_MAX + 1.0) + 1;
//整数I的分为k段(1 <= k <= n )for (i = 0;
i < n;
i++)
{
m = 9.0 * rand() / (RAND_MAX + 1.0);
if (0 == i && 0 == m)
{
n -= 1;
continue;
}df[i] = m;
}fprintf(fp, "%d %d\n", n,k);
for (i=0;
i < n;
i++)
fprintf(fp, "%d",df[i]);
fclose(fp);
return 0;
}/* -------------------------------------------------------------------*/
/**
* @Synopsis=ReadFile 从文件中读取所保存的正整数I及其长度,和要分的段数
*
* @Param= a[] 用来存储正整数I,info[]用来存储I的长度和所要分的段数k
*
* @Returns= 检验函数是否正确执行
*/
/* ----------------------------------------------------------------------------*/
int ReadFile(char a[],int info[])
{
FILE *fp;
int i;
int I_length = 0;
fp = fopen("input.txt","r");
if (NULL == fp)
{
perror("fopen");
exit(1);
}fscanf(fp,"%d%d\n",&info[0],&info[1]);
printf("%d %d\n",info[0],info[1]);
for (i = 1;
i <= info[0];
i++)
{
fscanf(fp,"%c",&a[i]);
}fclose(fp);
return 0;
}/* -------------------------------------------------------------------*/
/**
* @Synopsis=intergration_num 将i~j位的十进制数合并成一个十进制数
*
* @Param= a[] 保存的是正整数I
* @Param= start 划分的起始位
* @Param= end 划分的终止位
*
* @Returns= 返回合并后的数值
*/
/* -------------------------------------------------------------------*/
int intergration_num(char a[],int start,int end)
{
long sum=0;
int i;
for (i = start;
i <= end;
i++)
{
sum = a[i] - 48 + sum * 10;
}return sum;
}/* -------------------------------------------------------------------*/
/**
* @Synopsis=count_max_k_product计算最大k乘积
*
* @Param= a[] 存储有正整数I
* @Param= I 保存的是正整数I的长度,
* @Param= K 保存的是所分的段数
* @Param = index[] 用来回溯记录最近一次的划分位置
* @Returns= 返回值用来验证函数是否成功执行
*/
/* ----------------------------------------------------------------------------*/
int count_max_k_product(char a[], int I,int K,int index[])
{
int i,j;
int k_max[I][K] ;
//k_max[i][j]表示1 ~ i十进制位分成j段所得的最大乘积
int sum =0, temp = 0;
//分成一段
if (1 == K)
{
sum = intergration_num(a,1,I);
return sum;
}//假设先从最后一个数划分开,然后再乘上前面的k-1个不同划分的积,
//找最大值,然后从倒数第二个数划分开,然后再乘上前面k-2个不同划分的积,
//找到最大值,与前一个最大值比较得到最大值,然后从倒数第三个划分开,一
//次类推,直到倒数第I-(K-1)个数为止,for (i = I;
i >= K;
i--)
{
index[K-1] = i-1;
//表示在第i-1个的数后面划分
temp = count_max_k_product(a,i-1,K-1, index,f) * intergration_num(a,i,I);
if (sum < temp)
{
sum = temp;
}
}return sum;
}int main(int argc, char *argv[])
{
int info[2];
char a[ARRAY_SIZE];
int sum=0;
int index[ARRAY_SIZE], fd[ARRAY_SIZE];
int i, j = 1;
//其下为函数调用WriteFile();
ReadFile(a,info);
sum = count_max_k_product(a,info[0],info[1],index);
printf("%s分成%d段的最大乘积: %d\n",a+1,info[1],sum );
return EXIT_SUCCESS;
}
【动态规划之 最大k乘积】
推荐阅读
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- C/C++|C/C++ basis 02
- Qt实战|Qt+OpenCV联合开发(二十一)--图像翻转与旋转
- Qt实战|Qt+OpenCV联合开发(十四)--图像感兴趣区域(ROI)的提取
- Qt实战|Qt+OpenCV联合开发(十三)--通道分离与合并
- opencv|Qt+OpenCV联合开发(十六)--图像几何形状绘制
- Qt实战|Qt+OpenCV联合开发(十七)--随机数与随机颜色
- SNAT的MASQUERADE地址选择与端口选择
- IPTABLES的连接跟踪与NAT分析
- IPVS分析