滴滴出行 数字和为sum的方法数(dp)

给定一个有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;
}

猜你喜欢

转载自blog.csdn.net/ab1605014317/article/details/83615060