|
- //100分成6个数字的和
- #include <iostream>
- #include <cstdio>
- #include <iomanip>
- using namespace std;
- const int maxm=20; //100太大了 20 来验证
- const int maxn=7;//0位作废
- int ss;
- int a[maxn];
- int d[maxm+1][maxn];
- int z[7]={0,maxm/6,maxm/5,maxm/4,maxm/3,maxm/2,maxm}; //每个数字的最大值 显然第一个数字不可能超过100/6
- void mysearch(int i) //递归的做法
- {
- int j,k,s;
- if (i>=maxn-1)
- {
- s=a[1]+a[2]+a[3]+a[4]+a[5];
- a[6]=maxm-s; //计算出A[6]而不是枚举出a[6],减少一次递归,
- if (a[6]>=a[5])
- {cout<<setw(5)<<++ss<<':';for (j=1; j<=maxn-1; j++) cout<<a[j]<<' ';
- cout<<endl;}
- }
- else for (k=a[i-1]; k<=z[i]; k++) {a[i]=k;mysearch(i+1);}
- }
- void pp()
- {
- int i,j;
- cout<<"=====================\n";
- for (j=0;j<=6;j++)
- {for (i=0;i<=21;i++) cout<<setw(4)<<d[i][j];cout<<endl;}
- }
- int dp(int m,int n) //动态规划的做法
- { int i,j,k;
- for(i=1;i<=maxm;i++) {d[i][1]=1; //任何数字分成1个数字有一种做法;
- d[i][2]=i/2;}//任何数字分成2个数字有i/2种做法;
- for(i=2;i<=maxm;i++)
- for(j=2;j<=maxn-1;j++)
- if (i>=j) d[i][j]=d[i-1][j-1]+d[i-j][j]; //这个公式要认真思考!!!
- /*把100分成6份等价于两种分法的和
- 1、99分成5份,最后加一份1
- 2、95分成6份,每份加上1
- 这两种分法之间没有重复,并且加起来覆盖了全部 */
- return d[m][n];
- }
- int main()
- {
- //freopen("1.txt","w",stdout);
- a[0]=1;mysearch(1);
- cout<<dp(maxm,6);
- pp();
- }
复制代码
|
|