思路一
很简单的题目。不过是在01背包上增加约束而已。
思路:对于物品i分两种情况,放或者不放,计算那种情况可以获得的背包总价值最大,就是答案了。
总结下自己的错误点:放物品前需要判断:1.该组别是否已经放过 2.放入该物品是否会背包溢出!!!
#include<bits/stdc++.h>
#define UP(i,x,y) for(int i=x; i<=y; i++)
#define LEN 999
using namespace std;
int w[LEN]; // 重量
int c[LEN]; // 价值
int p[LEN]; // 第i号物品的组别
int bookGroup[100]={0}; // 第i组是否已经选取
int v,n,t;
vector<int> arr;
int k ;
/*
i: 第i个物品
syM: 剩余的重量
*/
int dfs(int i, int syW)
{
int temp1 = 0;
int temp2 = 0;
if(i == n + 1)
{
return 0;
}
/* 放入i物品获得的背包总最大价值 temp1 */
if(bookGroup[p[i]] == 0)
{
if(syW - w[i] >= 0)
{
bookGroup[p[i]] = 1;
temp1 = c[i] + dfs(i+1, syW - w[i]);
bookGroup[p[i]] = 0;
}
}
/* 不放入i物品获得的背包总最大价值 temp2 */
temp2 = dfs(i+1, syW);
return max(temp1, temp2);
}
int main()
{
cin>>v>>n>>t;
UP(i, 1, n)
{
cin>>w[i];
cin>>c[i];
cin>>p[i];
}
cout<<dfs(1, v);
return 0;
}
思路二
将每个组别看成一个超大的物品,这个物品里面还有很多小物品。这样的好处是后面记忆化方便点。
#include<bits/stdc++.h>
#define UP(i,x,y) for(int i=x; i<=y; i++)
#define LEN 9999
using namespace std;
int w[LEN]; // 重量
int c[LEN]; // 价值
int p[LEN]; // 第i号物品的组别
vector< vector<int> > g(LEN); // 组
//int bookGroup[100]={0}; // 第i组是否已经选取
int dp[LEN][LEN] = {0};
int v, n, t;
/*
i: 第i组
syM: 剩余的重量
return 还剩syM空间,放入i~t组 能获得的最大价值是多少
*/
int dfs(int i, int syW)
{
int temp1 = 0;
int temp2 = 0;
if(i == t + 1)
{
return 0;
}
if(dp[i][syW] != 0)
{
return dp[i][syW];
}
/* 不放第i组的物品 */
temp1 = dfs(i+1, syW);
/* 放第i组的物品 */
/* 尝试放第i组的第j个物品 */
for(vector<int>::iterator j = g[i].begin(); j != g[i].end(); ++j)
{
/* 判断是否溢出背包空间 */
if(syW - w[*j] >= 0)
{
int tp = dfs(i+1, syW - w[*j]) + c[*j];
temp2 = max(tp, temp2);
}
}
return dp[i][syW] = max(temp1, temp2);
}
int main()
{
cin>>v>>n>>t;
UP(i, 1, n)
{
cin>>w[i];
cin>>c[i];
cin>>p[i];
g[p[i]].push_back(i);
}
cout<<dfs(1, v);
return 0;
}