赞
踩
小蓝在学习C+ +数组时,突发奇想想知道如果将一个连续的正整数数组拆分成两个子数组,然后对拆分出的两个子数组求和并做差,且差值正好等于一个固定的正整数,像这样同一连续的正整数数组拆分方案有多少种。
我们一起帮助小蓝设计一下规则:
如:N = 5, M = 1,连续正整数数组A={1, 2, 3, 4, 5}。符合条件的拆分方案有3种:
分别输入两个正整数N( 3 < N < 30 3<N<30 3<N<30)和M( 0 < M < 500 0<M<500 0<M<500),两个正整数由一个空格隔开
输出一个正例,表示1到N (包含1和N)连续的正整数数组中有多少种方案,使得拆分的两个子数组部分和的差值等于M
5 1
3
由于
n
n
n的规模较小,可以暴力搜索所有方案。在搜索的过程中,对于1~n的每个数字,都有两种选择,要么加入到集合A1,要么加入到集合A2。用两个变量s1
、s2
分别记录集合A1、A2的和。当前分支搜索结束后,如果s1
和s2
的差满足要求,则方案数增加1。
#include <iostream>
using namespace std;
int n, m, ans;
void dfs(int t, int s1, int s2)
{
if(t > n)
{
if(s1 - s2 == m) ans ++;
return;
}
dfs(t + 1, s1 + t, s2);
dfs(t + 1, s1, s2 + t);
}
int main()
{
cin >> n >> m;
dfs(1, 0, 0);
cout << ans << endl;
return 0;
}
再提供一种思路,对于1~n的每个数字,要么在集合A1中,要么在集合A2中,只有两种选择。因此,可以使用状态压缩的思想,将n个数的状态看作n位的二进制串,枚举所有状态空间,选择符合条件的方案即可。
注意:该算法的时间复杂度为 O ( 2 n × n ) O(2^n\times n) O(2n×n),所以当 n ≥ 25 n\ge25 n≥25时,会TLE。
#include <iostream>
using namespace std;
int main()
{
int n, m, sum = 0;
cin >> n >> m;
for(int i = 1; i < (1 << n) - 1; i ++)
{
int s1 = 0, s2 = 0;
for(int j = 0; j < n; j ++)
{
if((i >> j) & 1) s1 += j + 1;
else s2 += j + 1;
}
if(s1 - s2 == m) sum ++;
}
cout << sum << endl;
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。