给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数A[i](32位整数),以空格隔开。
输出描述:
输出所求的方案数
示例1
输入
复制
5 15 5 5 10 2 3
输出
复制
4
这道题是给定一个数sum,求数组中是否存在几个数相加的和为sum的变形。
给定数组dp[i][j]表示组成j的情况在第i个值时有几种情况;要想符合情况就是有if(j > a[i])dp[i-1][j - a[i]] + dp[i][j-1];else dp[i-1][j];
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
using namespace std;
typedef long long ll;
const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-10;
const ll mod = 1e9 + 7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
int ret=0,f=0;char ch=getchar();
while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
return f?-ret:ret;
}
int n,sum;
ll a[maxn];
ll dp[maxn][maxn];
int main(){
scanf("%d%d",&n,&sum);
for(int i= 1; i<=n; i++){
scanf("%lld",&a[i]);
}
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;//赋初始值。表示第0个数组值构成0的情况是一种。
for(int i = 1; i <= n; i++){
for(int j = 0; j <= sum; j++){
if(j >= a[i]){
dp[i][j] = dp[i-1][j] + dp[i-1][j-a[i]];
}else{
dp[i][j] = dp[i-1][j];
}
}
}
printf("%lld\n",dp[n][sum]);
return 0;
}
方法二可以简化代码:
for(i=1;i<=n;i++)
for(j=sum;j>=a[i];j--)
dp[j]=dp[j-a[i]]+dp[j];
printf("%lld\n",dp[sum]);
和其相似的一道题:题目连接https://leetcode.com/problems/combination-sum-iv/description/
题目大意就是给定一个数组其中数组的值的个数不限问可以组成sum的种类有多少。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
using namespace std;
typedef long long ll;
const int maxn = 100 + 10;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-10;
const ll mod = 1e9 + 7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
int ret=0,f=0;char ch=getchar();
while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
return f?-ret:ret;
}
int n, m;
int a[maxn];
int dp[maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i ++){
scanf("%d",&a[i]);
}
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 1; i <= m; i++){
for(int j = 0; j <= n; j++){
if(i >= a[j]){
dp[i] += dp[i-a[j]];
}
}
}
printf("%d ",dp[m]);
return 0;
}