HDU-2602 Bone Collector(01背包)
Bone Collector
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
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
15 101 2 3 4 55 4 3 2 1
Sample Output
14
Author
Teddy
Source
HDU 1st “Vegetable-Birds Cup” Programming Open Contest
Recommend
lcy | We have carefully selected several similar problems for you: 1203 2159 2955 1171 2191
01背包(ZeroOnePack): 有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
01背包就是取还是不取的问题
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 1010
int dp[MAXN][MAXN]; //dp[i][j]表示i个物品,体积为j时的最大价值
int value[MAXN],w[MAXN];
int main()
{
int t;
int n,v;
int i,j;
scanf("%d",&t);
while(t--)
{
int maxn=-1;
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&v);
for(i=1;i<=n;i++)
scanf("%d",&value[i]);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
for(i=1;i<=n;i++)
for(j=v;j>=0;j--) //体积是从大到小变化的, for(j=0;j<=v;j++) 也是可以的
{ //也就是说这里是有两种情况讨论的
if(j>=w[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+value[i]);//不要当前物品是i-1来的,
//要也是i-1来的
else
dp[i][j]=dp[i-1][j]; //一开始是没这个物品的,装不下的话也只能这样
//当前的i是要保存值的。
maxn=max(maxn,dp[i][j]); //不一定就是取n个物品价值最大
}
cout<<maxn<<endl;
}
return 0;
}
PAT (Top Level) Practice PTA1002 Business (35 分)
As the manager of your company, you have to carefully consider, for each project, the time taken to finish it, the deadline, and the profit you can gain, in order to decide if your group should take this project. For example, given 3 projects as the following:
- Project[1] takes 3 days, it must be finished in 3 days in order to gain 6 units of profit.
- Project[2] takes 2 days, it must be finished in 2 days in order to gain 3 units of profit.
- Project[3] takes 1 day only, it must be finished in 3 days in order to gain 4 units of profit.
You may take Project[1] to gain 6 units of profit. But if you take Project[2] first, then you will have 1 day left to complete Project[3] just in time, and hence gain 7 units of profit in total. Notice that once you decide to work on a project, you have to do it from beginning to the end without any interruption.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤50), and then followed by N lines of projects, each contains three numbers P, L, and D where P is the profit, L the lasting days of the project, and D the deadline. It is guaranteed that L is never more than D, and all the numbers are non-negative integers.
Output Specification:
For each test case, output in a line the maximum profit you can gain.
Sample Input:
4
7 1 3
10 2 3
6 1 2
5 1 1
Sample Output:
18
不降维解法:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 55
struct Node
{
int cost;
int l;
int t;
}a[MAXN];
int dp[55][10000];
bool cmp(Node a,Node b)
{
return a.t<b.t;
}
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].cost,&a[i].l,&a[i].t);
}
sort(a+1,a+n+1,cmp);
int maxn=-1;
int deadline=a[n].t;
for(i=1;i<=n;i++)
for(j=deadline;j>=0;j--)
{
if(j>a[i].t) continue; //枚举所有的情况
else
{
if(j>=a[i].l)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i].l]+a[i].cost);
else
dp[i][j]=dp[i-1][j];
}
maxn=max(maxn,dp[i][j]); //不一定取n件物品价值就是最高
}
printf("%d\n",maxn);
return 0;
}
降维解法:
时间一维为dp,枚举的for循环不降维
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 1000
struct Node
{
int cost;
int l;
int t;
}a[MAXN];
int dp[100000];
bool cmp(Node a,Node b)
{
if(a.t!=b.t)
return a.t<b.t;
else
return a.l<b.l;
} //这个排序是有必要的,贪心的思想,期限短的先处理。
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].cost,&a[i].l,&a[i].t);
}
sort(a+1,a+n+1,cmp);
int deadline=a[n].t;
int maxn=-1;
for(i=1;i<=n;i++)
for(j=deadline;j>=0;j--)
{
if (j > a[i].t) continue;
else
{
if(j>=a[i].l) dp[j]=max(dp[j],dp[j-a[i].l]+a[i].cost);
else dp[j]=dp[j];
}
maxn=max(maxn,dp[j]);
}
printf("%d\n",maxn);
return 0;
}