c语言最大k乘积动态规划,动态规划之 最大k乘积

#include #define ARRAY_SIZE 11 /*定义数组大小 */

/*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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值