动态规划习题笔记(一)

Subset Sums
题目如下:
对于从1到N的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的。
举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,他们每个的所有数字和是相等的:
{3}and {1,2}
这是唯一一种分发(交换集合位置被认为是同一种划分方案,因此不会增加划分方案总数)
如果N=7,有四种方法能划分集合{1,2,3,4,5,6,7},每一种分发的子集合各数字和是相等的:
{1,6,7} and {2,3,4,5} {注 1+6+7=2+3+4+5}
{2,5,7} and {1,3,4,6}
{3,4,7} and {1,2,5,6}
{1,2,4,7} and {3,5,6}
给出N,你的程序应该输出划分方案总数,如果不存在这样的划分方案,则输出0。程序不能预存结果直接输出。

思路:

用动态规划的方法,题目要求可以转化成求对于最大为N的连续整数,和为(N+1)*N/4的方法数。

T(N,(N+1)*N/4)=T(N-1, (N+1)*N/4-N)+T(N-1, (N+1)*N/4)

最终的结果输出时除以二即可

还有一点就是如果数字之和为奇数,本就不可能有解,可以直接判断

#include<iostream>
#include<string.h>

using namespace std;

int N;
int ** matrix;
int ** flag;
int dfs(int N,int sum)
{
	if(sum<0||N==0)
	{
		return 0;
	}
	if(sum>(((N+1)*N)>>1))
	{
		return 0;
	}
	if(sum==(((N+1)*N)>>1)||sum==0||sum==1)
	{
		return 1;
	}
	if(flag[N][sum])
	{
		return matrix[N][sum];
	}
	matrix[N][sum]=dfs(N-1,sum-N)+dfs(N-1,sum);
//	cerr<<N<<' '<<sum<<' '<<matrix[N][sum]<<endl;
	flag[N][sum]=1;
	return matrix[N][sum];
}

int main()
{
	cin>>N;
        if((((N+1)*N)>>1)%2)
        {
          cout<<"0"<<endl;
          return 0;
        }
	int sum=(((N+1)*N)>>2);
	matrix=new int *[N+1];
	flag=new int *[N+1];
	for(int i=0;i<=N;i++)
	{
		matrix[i]=new int[sum+1];
		flag[i]=new int[sum+1];
		memset(matrix[i],0,sizeof(int)*(sum+1));
		memset(flag[i],0,sizeof(int)*(sum+1));
	}
	cout<<dfs(N,sum)/2;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值