滴滴出行 數字和為sum的方法數(dp)
阿新 • • 發佈:2018-12-22
給定一個有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; }