前几天找到一个有意思的题目
要求是键盘中输入一个数字,然后在屏幕上输出它所有的划分情况,例如:
input : 4
output:
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
查了百度后发现是acm中的整数划分问题的变形,原题是计算出有多少种分法。
对于我来说,即便知道了acm的算法,解出此题还是有些困难的,毕竟分的数量
只需用一个变量记住递归次数就好,但真正要把结果打印在屏幕上要考虑的因素
要多的多(比如每一行要有个 x = a + b+.... 用递归就感觉有些麻烦了 )
于是我想改变下思路:
用数组去接收每一次划分的方法,划分完成后再依次输出数组中的值从而实现屏幕输出效果。
1. 将数据逐层划分,直到分成x = 1 +1 +......为止
例如: 6 = 5 + 1
6 = 4 +1 + 1
6 = 4 + 2
6 = 3 .........
...........
6 = 1........
2. 在针对每一层进行处理:
分别求出它们的最大以及最小划分长度
例如: 针对 以4 打头的那一层:
当其余加数全部为1 的时候,数组达到最长划分长度
当其余加数的数目尽可能少,数组达到最短划分长度
(注意:其余的加数不能够大于打头的数字)
3. 对最长划分长度数组进行操作,将数组中最后一个值加到数组中的第二个位置,
后将最后一个数销毁,从而得到一个新的划分方式
例如:a[0] = 4, a[1] = 1, a[2] = 1
将a[2]加到a[1]中, 并将a[2]销毁
得到一个新的划分方式a[0] = 4, a[1] = 2
(注意:同样的a[1]不能够大于a[0],因此第二个位置其实是相对位置,如果a[1]==a[0]
那么相应的尾巴上的数应该加到a[2]上)
4. 重复步骤三,每划分一次输出一次,直到数组长度缩减到
最短划分长度,一次循环函数结束
(当达到最短划分长度时,数据已经无法再细分,要结束这层的循环进入下一次的迭代)
OK,弄清楚思路以后解题就方便了:
#include <stdio.h>
#include <stdlib.h>
#define N 100
#include <stdlib.h>
#define N 100
// 计算数组长度
int len_of_a(int a[])
{
int i;
for(i = 1; a[i] != '\0';)
{
i++;
}
return i;
}
int len_of_a(int a[])
{
int i;
for(i = 1; a[i] != '\0';)
{
i++;
}
return i;
}
// 输出一种划分方法
void my_output(int a[],int sizeof_a)
{
//数组, sizeof_a = 数组长度
int i;
printf("%d", a[0]);
for(i = 1; i< sizeof_a; i++)
{
printf("+%d", a[i]);
}
printf("\n");
}
// 比较现在数组长度,如果大于最短长度则继续缩短数组长度
void my_compare(int k, int less_len, int a[])
{
//k = 数组长度, less_len = 最小长度, 数组
int z = 1;
while(k > less_len)
{
if(a[z] < a[0])
{
a[z] += a[k-1];
a[k-1] = '\0';
k--;
}
else
{
z++;
a[z] += a[k-1];
a[k-1] = '\0';
k--;
}
my_output(a, k);
}
}
// 整数划分
void my_divide(int number)
{
int sum = 0;
int a[N];
int k ;//数组下标
int i = number - 1;
for(i = number - 1; i >= 1; i--)
{
//强行锁定数组第一个元素
a[0] = i;
{
//强行锁定数组第一个元素
a[0] = i;
for(k = 1; (sum += a[k-1]) != number; k++)
{
//确定数组最长长度为k,即把数字分成 number = i +1 +1 +1 +.....+1的形式
{
//确定数组最长长度为k,即把数字分成 number = i +1 +1 +1 +.....+1的形式
a[k] = 1;
}
//终止符
}
//终止符
a[k] = '\0';
//记录数组最短长度
int less_len;
if(number % i == 0)
{
less_len = number / i;
}
else
{
less_len = (number / i) + 1;
}
int less_len;
if(number % i == 0)
{
less_len = number / i;
}
else
{
less_len = (number / i) + 1;
}
//计算数组得到最长长度
k = len_of_a(a);
my_output(a,k);
my_compare(k, less_len, a);
my_compare(k, less_len, a);
sum = 0;
}
}
}
}
int main()
{
int n;
scanf("%d", &n);
my_divide(n);
return 0;
}
(程序我还没有系统地整理过,函数的命名以及一些地方备注,算法的优化,输出格式后续会慢慢修改,
主要先把思路记录下来)