本题很显然是动态规划(完全背包)。诸如此类让蒟蒻选择n个物体的问题基本上都可以用动态规划解决。但是和传统的动态规划不同的是,这里要求大于等于所给钱数且最少的方案,而传统背包只能是小于等于容量,怎么办呢???
答案:得加钱!
仍然以传统背包方式计算,但是计算的钱数可以大于目标钱数(题目中描述是不超过所有之和)。然后再依次判断目标钱数及以上的背包,发现第一个大于等于目标钱数的输出即可。
小结:动态背包dp[i][j],如果固定i不变,j不断增大,其得到的数列就是由i个物体能够构成的价值的递增序列,本次做法原理就是在这个数列中找到目标数。
cpp
#include <bits/stdc++.h>
using namespace std;
#define MAX 400000
int prime[32][MAX] = {0};
int main()
{
int goods[32] = {0};
int num_g=0, money=0;
cin>>num_g>>money;
int all=0;
for(int i=0;i<num_g;i++)//初始化
{
cin>>goods[i];
all+=goods[i];
}
for(int i=goods[0];i<=all;i++)//对第一个物品单独处理,因为他参与下面循环会报错(越界)
{
prime[0][i] = goods[0];
}
for(int i=1;i<num_g;i++)
{
for(int j=0;j<=all;j++)
{
if(goods[i]>=j)
{
prime[i][j] = prime[i-1][j];
}
else
{
prime[i][j] = max(goods[i]+prime[i-1][j-goods[i]],prime[i-1][j]);
}
}
}
for(int i=money;i<=all;i++)
{
if(prime[num_g-1][i]>=money)
{
cout<<prime[num_g-1][i];break;
}
}
//for(int i=0;i<=all;i++)//----------------------------输出结果以查看
//{
// for(int j=0;j<num_g;j++)
// {
// cout<<prime[i][j]<<' ';
//
// }cout<<endl;
//}
return 0;
}