多重背包可行性问题

举个问题:有n种不同大小的数字ai,每种各mi个。判断是是否可以从这些数字中选出若干个使他们的和为k。

代码加注释如下:

#include<stdio.h>
#include<string.h>
#include<algorithm>
int dp[1000], a[1000], m[1000];
int max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int n, k;
scanf_s("%d%d", &n, &k);
for (int i = 0; i < n; i++)
scanf_s("%d%d", &a[i], &m[i]);
memset(dp, -1, sizeof(dp));
dp[0] = 0;


/*背包九讲可行性问题中的代码*/
for (int i = 0; i < n; i++)//正推
{
for (int j = 0; j <= k; j++)//i之前能满足,v=j,也就是不用消耗物品就达到v=j,剩下m[i]件第i件物品
{
if (dp[j] >= 0)
dp[j] = m[i];
else
dp[j] = -1;
}
for (int j = 0; j <= k - a[i]; j++)//v=j时,物品剩下,可以继续再放一个(直到v=k),同时消耗一件物品,比较dp[j]-1和dp[j+a[i]](之前的状态,若之前能满足就是m[i],不然就是-1(看上一个循环))
if (dp[j] > 0)
dp[j + a[i]] = max(dp[j+a[i]],dp[j]-1);
}

/*直接分情况讨论*/
/*for (int i = 0; i < n; i++)
for (int j = 0; j <= k; j++)
if (dp[j] >= 0)//已经知道可以填满了,所以不用消耗第i件物品就可以填满(前i-1件物品有达到v=j的方法),所以第i件物品一件也没消耗,dp[j]=M[i]; v=0时,
dp[j] = m[i];
else if (j < a[i] || dp[j - a[i]] <= 0)//j < a[i]时,放不下; -1时,放一件发现不可能填满; 0时,第i件物品都放了,没得放 ;
dp[j] = -1;
else
dp[j] = dp[j - a[i]] - 1;//dp[j - a[i]]为v=j-a[i]时,剩下的第i件物品,再消耗一件第i件物品就可以满足v=j;
*/


puts(dp[k] >= 0 ? "Yes" : "No");
return 0;
}

猜你喜欢

转载自www.cnblogs.com/hide-in-theweb/p/11687092.html
今日推荐