想试试PTA Top Level的难度,然后随便来了一题~
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:
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.
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.
For each test case, output in a line the maximum profit you can gain.
4
7 1 3
10 2 3
6 1 2
5 1 1
Sample Output:
18
很明显的01背包问题,我们知道普通01背包不论枚举物品的顺序如何对最终结果都是没有影响的。
而本题中由于deadline的限制,需要按照deadline从小到大排个序(这样后面想替换掉前面的才方便),然后开始枚举选和不选这件物品才可以保证得到正确的结果。
dp[i][j]
前i件物品中,当第i件放入容量为j的背包可以获得的最大利润。
需要注意的是 枚举的容量大于这件物品的deadline后:
dp[i][j-1]
dp[i-1][j]
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
#include
#include
using namespace std;
const int N = 55;
const int MAX = 1e5;
struct Project
{
int p,l,d;
bool operator <(const Project x) const{
return d < x.d;
}
} a[N];
int dp[N][MAX];
int main()
{
int n;
cin>>n;
int maxx = 0;
for(int i = 1; i <= n; ++i)
{
cin>>a[i].p>>a[i].l>>a[i].d;
maxx = max(maxx,a[i].d);
}
sort(a+1,a+n+1);
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= maxx; ++j)
{
if(j <= a[i].d)
if(j - a[i].l < 0)
dp[i][j] = dp[i-1][j];
else if(j - a[i].l == 0)
dp[i][j] = max(dp[i-1][j],a[i].p);
else
dp[i][j] = max(dp[i-1][j],dp[i-1][j-a[i].l]+a[i].p);
else
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
/*for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= maxx; ++j)
{
cout<
cout<<dp[n][maxx]<<endl;
return 0;
}
/*
6
7 1 3
10 2 3
6 1 2
5 1 1
26 6 7
1 1 8
*/
本题我A了后打算压缩空间复杂度,但是我发现上面提到的当超过deadline部分修改成:
dp[j] = max(dp[j],dp[j-1]);
因为是倒着算,当dp[j-1]在要用的时候却没有算出来(当背包容量超过当前枚举到的物品时的deadline,我打算选这个物品的时候)。。
应该是我处理方式不对,想了好久,还是压缩空间复杂度失败,留坑!!!
#include
#include
using namespace std;
const int N = 55;
const int MAX = 1e5;
struct Project
{
int p,l,d;
bool operator <(const Project x) const
{
return d < x.d;
}
} a[N];
int dp[MAX];
int main()
{
int n;
cin>>n;
int maxx = 0;
for(int i = 1; i <= n; ++i)
{
cin>>a[i].p>>a[i].l>>a[i].d;
maxx = max(maxx,a[i].d);
}
sort(a+1,a+n+1);
for(int i = 1; i <= n; ++i)
{
for(int j = maxx; j > 0; --j)
{
if(j <= a[i].d)
{
if(j - a[i].l >= 0)
dp[j] = max(dp[j],dp[j-a[i].l]+a[i].p);
}
else
dp[j] = max(dp[j],dp[j-1]); //这里不能这样!!!!
}
}
cout<<dp[maxx]<<endl;
return 0;
}