这个问题,我初看还以为简单,但是想了很久,还没做出来。
整数的分划问题。如,对于正整数n=6,可以分划为:5+14+2,4+1+13+3,3+2+1,3+1+1+12+2+2,2+2+1+1,2+1+1+1+11+1+1+1+1+1问题是,对于用户输入的正整数n(范围1~10),输出所有划分。
希望大家帮忙下。
[解决办法]
楼上的代码当des=2时有bug,这里修改了一下。
void sub_add_2(int des){ int *a = new int[des]; for(int i=1; i<des; ++i) { a[i] = des/i; } int *b = new int[des+2]; b[1] = des; for(i=2; i<des+2; ++i) { b[i] = 0; } while(b[des]<1) { int sum = 0; for(int i=1; i<des; ++i) { sum += b[i]*i; } if(sum==des) { for(int i=1; i<des; ++i) { if(b[i]>0) { for(int temp=b[i]; temp>0; --temp) { cout<<i<<" "; } } } cout<<endl; b[1] = 0; ++b[2]; } else { ++b[1]; } for(i=1; i<des && b[i]>a[i]; ++i) { b[i] = 0; ++b[i+1]; } }}int main(){ int des; cin>>des; sub_add_2(des); return 0;}
[解决办法]
讲一下思路:
1 : 1
2 : 1+1,2
3 : 1+1+1,2+1,3
4 :1+1+1+1,2+1+1,3+1,2+2,4
5 :1+1+1+1+1,2+1+1+1,3+1+1,2+2+1,4+1,3+2,5
6 : 1+1+1+1+1+1,2+1+1+1+1,3+1+1+1,2+2+1+1,4+1+1,3+2+1,5+1,4+2,3+3,6
7 : 1+1+1+1+1+1+1,2+1+1+1+1+1,3+1+1+1+1,2+2+1+1+1,4+1+1+1,3+2+1+1,5+1+1,4+2+1,3+3+1,6+1,3+2+2,5+2,4+3,7
规律:
由上面可以知道使用递推便可完成,求第n项时
1> 将n-1所有项全部拉下来,将其后面全部+1构成组合
2> 将n-1所有项中倒数第二位大于倒数第一位的所有项提出,然后给倒数第一位+1构成新组合
实现方式,将申请一个三维数组,保存所有划分结果,递推时,只要简单将上次的结果拉下来,并加一,并判断第二种情况即可,该方法不适于大型数字划分,十分耗内存
[解决办法]
10楼的算法效率太低,当des>20时,算的很慢,进行了一下优化,效率大幅度提高。
void sub_add_2(int des){ int *a = new int[des]; for(int i=1; i<des; ++i) { a[i] = des/i; } int *b = new int[des+2]; b[1] = des; for(i=2; i<des+2; ++i) { b[i] = 0; } while(b[des]<1) { int sum = 0; for(int i=1; i<des; ++i) { sum += b[i]*i; } if(sum==des) { for(int i=1; i<des; ++i) { if(b[i]>0) { for(int temp=b[i]; temp>0; --temp) { cout<<i<<" "; } } } cout<<endl; b[1] = 0; ++b[2]; } else { if(sum<des) { b[1] += (des-sum); } else { for(int i=1; i<des && b[i]==0; ++i); b[i] = 0; ++b[i+1]; } } for(i=1; i<des; ++i) { if(b[i]>a[i]) { b[i] = 0; ++b[i+1]; } } }}