思路:
动态规划题,因为要判断前n个物品能拼成重量为40的数目,我们要把他分解为子问题,就是前i个物品能拼成重量为a的数目,然后再看是什么条件影响了当前的状态,那就是减去第i个位置的物品之后前i-1所能拼成的数目,此时分解的子问题就没有后效性了。
1.动态规划的解法
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<cctype>
#include<vector>
#include<limits.h>
#include<queue>
using namespace std;
int p[30];
int dp[50][30];
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=1; i<=n; ++i)
{
scanf("%d",&p[i]);
}
for(i=0; i<30; ++i)
{
dp[0][i]=1;
}
for(i=1; i<=40; ++i)
{
for(j=1; j<=n; ++j)
{
dp[i][j]=dp[i][j-1];
if(i-p[j]>=0)
dp[i][j]+=dp[i-p[j]][j-1];
}
}
printf("%d\n",dp[40][n]);
return 0;
}
2. 只是内外两个for循环的遍历不同,思路想法应该都是一样的
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<cctype>
#include<vector>
#include<limits.h>
#include<queue>
using namespace std;
int p[30];
int dp[30][50];
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=1; i<=n; ++i)
{
scanf("%d",&p[i]);
}
for(i=0; i<30; ++i)
{
dp[i][0]=1;
}
// for(i=1;i<=40;++i)
// {
// for(j=1;j<=n;++j)
// {
// dp[i][j]=dp[i][j-1];
// if(i-p[j]>=0)
// dp[i][j]+=dp[i-p[j]][j-1];
// }
// }
for(i=1; i<=n; ++i)
{
for(j=1; j<=40; ++j)
{
dp[i][j]=dp[i-1][j];
if(j-p[i]>=0)
dp[i][j]+=dp[i-1][j-p[i]];
}
}
printf("%d\n",dp[n][40]);
return 0;
}
3.递归的解法
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<cctype>
#include<vector>
#include<limits.h>
#include<queue>
using namespace std;
int p[30];
int dp(int w, int k)
{
if(w==0)
return 1;
if(k<=0)
return 0;
return dp(w,k-1)+dp(w-p[k],k-1);
}
int main()
{
int n,i;
scanf("%d",&n);
for(i=1; i<=n; ++i)
{
scanf("%d",&p[i]);
}
printf("%d\n",dp(40,n));
return 0;
}