| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 542 | Accepted: 149 |
Description
For example your friend Jack wants to travel on the Mediterranean Sea for 20 days and has the following choices:
- if the holiday deadline is 60 days you can get 1000 EUR provided the boat is rented in between 0 and 41 (60days-20days+1) for 20 days;
- if the holiday deadline is 70 days you can get 800 EUR.
If a client does not contribute to the maximization of your profit you can drop that client. You know all the clients and their choices and you must rent the boat according to the order in which the clients submit their requests.
Write a program that, given the clients, computes the largest profit you can get.
Input
- n - the number of clients (n <= 100)
- on n separate lines the number of days (at most 100) each client wishes to rent the boat;
- the total number of choices for all clients;
- the list of choices in the format client_id, deadline, amount_of_money where the client id is a positive integer in the range 1..n and deadline <= 100.
An empty line separates the input data sets.
Output
Sample Input
3 2 2 4 4 1 2 14 3 4 25 2 4 12 3 3 10
Sample Output
26
题目大意:每个客户要问你借船几天,他们都要在截止日期前归还才能获益。如客户iii借船20天,截止日期是60天,那么你在0~41天之间借给他都可以获益。
其实是价值变化的01背包问题,在某天前借给客户则有价值,否则价值为0.
传统的01背包,容量是ccc,iii个物品每个占xxx容量,价值为vvv。
动规公式为:dp[j]=max(dp[j],dp[j−cost[i]]+value[i])dp[j] = max(dp[j],dp[j-cost[i] ]+value[i])dp[j]=max(dp[j],dp[j−cost[i]]+value[i])
这道题为:
- 最多借100天(容量为100)
- nnn个客户(nnn个物品)
- 每个客户借daydayday天(每个占daydayday容量)
- 截止日期bbb前归还则有收益ccc(daydayday~bbb的容量之间才有价值ccc)
day[i]day[i]day[i]表示客户iii借的天数,dp[j]dp[j]dp[j]表示前jjj天最大收益,num[i][j]num[i][j]num[i][j]表示在第jjj天收回客户iii的船的收益。
动规公式为:dp[j]=max(dp[j],dp[j−day[i]]+num[i][j])dp[j] = max(dp[j],dp[j-day[i]]+num[i][j])dp[j]=max(dp[j],dp[j−day[i]]+num[i][j])
发现了吗?只有价值部分是不一样的,我们只要给daydayday~bbb的容量之间赋价值ccc,其余容量赋0即可。
注意题目要求每个结果之间输出一个空行
AC代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[110];
int num[110][110], day[110];
int main()
{
int t = 0, n, m, i, j, k, a, b, c, ans;
while (~scanf("%d", &n))
{
for (i = 1; i <= n; i++)
scanf("%d", &day[i]);
scanf("%d", &m);
memset(dp, 0, sizeof(dp));
memset(num, 0, sizeof(num));
while (m--)
{
scanf("%d%d%d", &a, &b, &c); //客户 截止日期 获益
for (j = b; j >= day[a]; j--) //在截止日期时收回,记得这里是逆序更新!
{
num[a][j] = max(num[a][j], c);
//printf("num[%d][%d] : %d\n", a, j, num[a][j]);
}
}
for (i = 1; i <= n; i++)
for (j = 100; j >= day[i]; j--)
{
dp[j] = max(dp[j], dp[j - day[i]] + num[i][j]);
//printf("dp[%d] : %d\n", j, dp[j]);
}
ans = 0;
for (i = 0; i <= 100; i++)
ans = max(ans, dp[i]);
if (t != 0)
printf("\n");
t++;
printf("%d\n", ans);
}
}
这篇博客介绍了POJ1278_BOAT问题,它是一个价值变化的01背包问题。每个客户有不同的租船天数和截止日期,只有在特定时间内归还船只才会有收益。博主通过动态规划的方法解析了问题,并提供了AC(Accepted)代码实现。
5332

被折叠的 条评论
为什么被折叠?



