计蒜客 等和的分隔子集

跟动态规划干上了,新的一道动态规划题目

晓萌希望将1到N的连续整数组成的集合划分成两个子集合,且保证每个集合的数字和是相等。例如,对于N=3,对应的集合{1,2,3}能被划分成{3} 和 {1,2}两个子集合.

这两个子集合中元素分别的和是相等的。

对于N=3,我们只有一种划分方法,而对于N=7时,我们将有4种划分的方案。

输入包括一行,仅一个整数,表示N的值(1≤N≤39)。

输出包括一行,仅一个整数,晓萌可以划分对应N的集合的方案的个数。当没发划分时,输出0。

样例输入

7

样例输出

4

解析

这题一看,没办法马上想出动态规划的方法,因为N=7和N=6没什么联系,所以不能通过N=6求N=7

然后打算使用递归来做,这个题目的意思就是在1-N的N个数里面任取k个数,使得k个数之和等于这N个数的和的一半,求有多少种取法,最后的结果减半就可以了。

定义一个数组int dp[1000][50]={0}; dp[x][y]代表在1-y的y个数里面取数,总和是x的情况有dp[x][y]种

用函数F(i,j)来求dp[i][j],求出来的每个dp[i][j]记录下来,如果之前求过就不需要再继续求

函数F分为4种情况

1.dp[i][j]已经求出,直接返回即可

2.i>=j的时候,dp[i][j]=不取j的情况 F(i,j-1) +取j的情况 F(i-j,j-1);    i<j时,dp[i][j]=dp[i][j-1];

3.j为0的时候,无数可取,返回0

4.i为0的时候,说明刚好取够,此时dp[i][j]=1,返回1

最后实现的时候,运行超时,说明这个方法还有待改进,等下次有空再发新的

优化后版本计蒜客 等和的分隔子集(优化)

代码

int dp[1000][50]={0};

int F(int number,int n)

{

if(dp[number][n]!=0)

{

}

else if(number==0)

{

dp[number][n]=1;

}

else if(n==0)

{

return 0;

}

else if(number>=n)

{

dp[number][n]=F(number,n-1)+F(number-n,n-1);

}

else

{

dp[number][n]=F(number,n-1);

}

return dp[number][n];

}

int main()

{

int N;

scanf("%d",&N);

int number=N*(N+1)/2;

if(number%2==0)

{

number=number/2;

printf("%d\n",F(number,N)/2);

}

else

{

printf("0\n");

}

return 0;}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,790评论 0 33
  • 动态规划(Dynamic Programming) 本文包括: 动态规划定义 状态转移方程 动态规划算法步骤 最长...
    廖少少阅读 3,374评论 0 18
  • 回溯算法 回溯法:也称为试探法,它并不考虑问题规模的大小,而是从问题的最明显的最小规模开始逐步求解出可能的答案,并...
    fredal阅读 13,808评论 0 89
  • 早上起床,叫媳妇吃饭!她习惯性的打开手机,不出所料-又在收钱…… 这不知道是第几次了,好像我也每天睡醒就收钱……
    分享秘密阅读 144评论 0 1
  • 一个人看过无数部电影 逛过无数次街 无数次的走在路上 看到别人三三两两结伴而行 而我… 大概孤独是人生常态吧 嗯。...
    hiyour阅读 73评论 0 0