Problem Description
Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?
Input
The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Output
One integer per line representing the maximum of the total value (this number will be less than 231).
Sample Input
1
5 10
1 2 3 4 5
5 4 3 2 1
Sample Output
14
许多年前,在泰迪的家乡有一个被称为“骨收集者”的人。这个人喜欢收集各种各样的骨头,比如狗的,牛的,他也去了坟墓…。
骨头收集者有一大袋V的体积,在他的收集之旅中有很多骨头,很明显,不同的骨头有不同的价值和不同的体积,现在给出每一块骨头沿着他的行程的价值,你能计算出骨头收集者能得到的总价值的最大值吗?。
输入。
第一行包含整数T,即案例数。
其次是T例,每例三行,第一行包含两个整数N,V,(N<;=1000,V<;=1000)表示骨数和包的体积。第二行包含N个整数,表示每个骨骼的值。第三行包含N个整数,表示每个骨骼的体积。
输出量。
每行一个整数,表示总值的最大值(此值将小于231)。
样本输入。
一。
5、10。
1 2 3 4 5。
5 4 3 2 1。
样本输出。
14
简单代码:
#include<bits/stdc++.h>
using namespace std;
long long int dp[1005], a[1005], b[1005];
int main()
{
int t;
cin >> t;
while (t--)
{
long long int n, v;
cin >> n >> v;
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i++)cin >> b[i];
for (int i = 1; i <= n; i++) //以下三列则是精髓
for (int j = v; j >= b[i]; j--)
dp[j] = max(dp[j], dp[j - b[i]] + a[i]);
cout << dp[v] << endl;
}
}
长一点的代码。。有人会问,丫丫丫,怎么看到的是关键三行的第一行应该是逆序(即i从n后边开始)但注意,我的输入比较特殊,我从1开始输入的,初始化为0的行为第一行因此我正序做就ok拉!!!
#include<bits/stdc++.h>
using namespace std;
long long int dp[1005][1005], a[1005], b[1005];
int main()
{
int t;
cin >> t;
while (t--)
{
long long int n, v;
cin >> n >> v;
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i++)cin >> b[i];
for (int i = 1; i <= n; i++)
//以下三列与上面的区别
for (int j = 0; j <= v; j++)
//这个j不能改成1,改成1AC不了,至于为啥,我也没搞清楚,我觉得是可以的,如果0体积有价值我也无话可说,所以0最保险,或者用上面的优化代码!!!!!
{
if (j < b[i])dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i-1][j - b[i]] + a[i]);
}
cout << dp[n][v] << endl;
}
}
找出最优解了,但里面装的是啥,我想确定咋办捏,然后找回去憋
#include<bits/stdc++.h>
using namespace std;
long long int dp[1005][1005], a[1005], b[1005], item[1005] = { 0 };
void FindWhat(int i, int j)//寻找解的组成方式
{
if (i >= 0)
{
if (dp[i][j] == dp[i - 1][j])//相等说明没装
{
item[i] = 0;//全局变量,标记未被选中
FindWhat(i - 1, j);
}
else if (j - b[i] >= 0 && dp[i][j] ==dp[i - 1][j - b[i]] + a[i])
{
item[i] = 1;//标记已被选中
FindWhat(i - 1, j - b[i]);//回到装包之前的位置
}
}
}
int main()
{
int t;
memset(dp, 0, sizeof(dp));
cin >> t;
while (t--)
{
long long int n, v;
cin >> n >> v;
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i++)cin >> b[i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= v; j++)
{
if (j < b[i])dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i-1][j - b[i]] + a[i]);
}
cout << dp[n][v] << endl;
FindWhat(n, v);
for (int i = 1; i <= n; i++)if (item[i])cout << a[i] << b[i] << endl;
}
}