pta 整数拆分

给定一个整数n,将其无序拆分成最大数为k的拆分数,(n,k不超出100) 要求:所有的拆分方案不重复。 如当n=4,k=4时,一共有5种拆分方案,拆分如下:

(1)4=1+1+1+1
(2)4=1+1+2
(3)4=1+3
(4)4=2+2
(5)4=4

输入格式:
每一行输入一组整数n,k,遇到键盘结束符^Z或文件结束符EOF时结束输入。

输出格式:
按行输出每组的拆分方案数。

这个题和整数拆分各项和不一样
本来打算用深搜做
只有第一个能过
错误代码
`#include<stdio.h>
int ans,sum,n,k;
void dfs(int x)
{
if(sum==n)
{
ans++;
}
if(sum>n) return;
for(int i=x;i<=k;i++)
{
sum+=i;
dfs(i);
sum-=i;
}

}
int main()
{
while(~scanf("%d,%d",&n,&k))
{
ans=0,sum=0;
dfs(1);
printf("%d\n",ans);
}
return 0;
}
`
后来看了下别人的代码
2. 动态规划

既然暴力的方法行不通,那么我们就该换种思路了。实在没有思路的时候我们可以尝试手动计算出n,k都较小时的拆分方案数。结果我们不难发现以下几条规律。

当n==1时,无论k为何值,都只有一种拆分方案。即{1}。

当k==1时,无论n为何值,都只有一种拆分方案。即{1,1,……,1,1}。因为拆分的最大数不能超过k,所以只能拆成1。

当n==k时,根据拆分出来的数是否包含n,可以分成两种情况。

拆分出来的整数包含n,那就只有一种情况,即{n}。
拆分出来的整数不包含n,那么这些拆分出来的数中,一定比n小,即n的所有(n-1)拆分。因此dp[n][k]=1+dp[n][k-1];
当n<k时,因为拆分出来的最大数永远不可能达到k。所以等价于n的所有n拆分。因此dp[n][k]=dp[n][n];

当n>k时,根据拆分出来的整数中是否包含k,可以分为两种情况:

拆分出来的整数中包含k,即{k,{a1,a2,……,ai}),其中{a1,a2,……,ai}的和为n-k,可能再次出现k,因此是(n-k)的k拆分。因此这种情况的拆分数是dp[n-k][k]。
拆分出来的整数中不包含k的情况,则拆分出来的整数中所有值都比k小,即n的(k-1)划分。拆分数为dp[n][k-1]。
所以dp[n][k]=dp[n-k][k]+dp[n][k-1]。
原文链接:https://blog.csdn.net/qq_43058685/article/details/103228145

#include<stdio.h>
int main()
{
    int n,k,i,j;
    int dp[202][202];
    while(~scanf("%d,%d",&n,&k))
    {
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=k;j++)
            {
                if(i==1||j==1)
                    dp[i][j]=1;
                else if(i==j)
                    dp[i][j]=1+dp[i][j-1];
                else if(i<j)
                    dp[i][j]=dp[i][i];
                else if(i>j)
                    dp[i][j]=dp[i-j][j]+dp[i][j-1];

            }
        }
        printf("%d\n",dp[n][k]);
	}
	return 0;
}

发布了6 篇原创文章 · 获赞 1 · 访问量 179

猜你喜欢

转载自blog.csdn.net/RUBGH/article/details/104543006
PTA