题意:有n种不同大小的数字ai,每种各mi个,判断是否可以从这些数字之中选出若干使他们的和恰好为k。
输入:
n=3
a={3,5,8}
m={3,2,2}
k=17
输出: YES(3*3+8)
代码实现:(白书62页就是,里面有详细的介绍,因为我本人那个排版的问题,暂时就先这样)
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
int dp[100][maxn],a[maxn],c[maxn];
//dp[i+1][j]:=用前i种数加和得到j时第i种数最多能剩余多少个(不能加和得到i的情况下为-1)
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
scanf("%d",&c[i]);
int k;
scanf("%d",&k);
memset(dp,-1,sizeof dp);
dp[0][0] = 0;
for(int i=0;i<n;i++)
{
for(int j=0;j<=k;j++)
{
if(dp[i][j] >= 0)
dp[i+1][j] = c[i];
else if(j<a[i] || dp[i+1][j-a[i]]<=0)
dp[i+1][j] = -1;
else
dp[i+1][j] = dp[i+1][j-a[i]]-1;
}
}
if(dp[n][k] >= 0)
printf("YES\n");
else
printf("NO\n");
return 0;
}
题目链接:http://poj.org/problem?id=1742
题意:与最上面的题意类似,就是恰好等于k改成小于等于k,求满足题意的数目(还不是太理解,写下来慢慢理解)降维
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ms(a) memset(a,0,sizeof a)
const int maxn = 1e5+10;
int a[maxn],c[maxn],dp[maxn];
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m)&&n+m)
{
ms(a);
ms(c);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
memset(dp,-1,sizeof dp);
dp[0] = 0;
for(int i=1;i<=n;i++)
{
dp[0] = c[i];
for(int j=1;j<=m;j++)
{
if(dp[j] >= 0)
dp[j] = c[i];
else if(j<a[i] || dp[j-a[i]]<=0)
dp[j] = -1;
else if(dp[j-a[i]]>=0)
dp[j] = dp[j-a[i]] - 1;
}
}
int cnt = 0;
for(int i=1;i<=m;i++)
{
if(dp[i] >= 0)
cnt++;
}
printf("%d\n",cnt);
}
return 0;
}