题目
题目描述
在《Harry Potter and the Chamber of Secrets》中,Ron的魔杖因为坐他老爸的Flying Car撞到了打人柳,不幸被打断了,从此之后,他的魔杖的魔力就大大减少,甚至没办法执行他施的魔咒,这为Ron带来了不少的烦恼。
这天上魔药课,Snape要他们每人配置一种魔药(不一定是一样的),Ron因为魔杖的问题,不能完成这个任务,他请Harry在魔药课上(自然是躲过了Snape的检查)帮他配置。 现在Harry面前有两个坩埚,有许多种药材要放进坩埚里,但坩埚的能力有限,无法同时配置所有的药材。一个坩埚相同时间内只能加工一种药材,但是不一定每一种药材都要加进坩埚里。加工每种药材都有必须在一个起始时间和结束时间内完成(起始时间所在的那一刻和结束时间所在的那一刻也算在完成时间内),每种药材都有一个加工后的药效。
现在要求的就是Harry可以得到最大的药效。
输入格式
输入文件的第一行有2个整数,一节魔药课的t(1≤t<≤500)和药材数n(1≤n≤100)。
输入文件第2行到n+1行中每行有3个数字,分别为加工第i种药材的起始时间t1、结束时间t2、(1≤t1≤t2≤t)和药效w(1≤w≤100)。
输出格式
只有一行,只输出一个正整数,即为最大药效。
题解
这道题目是一个双进程的01背包。
设出状态
- 放进第一个锅
- 放进第二个锅
- 不放入锅
所以我们可以写出状态转移方程:
- f[j][k]=max(f[j][k],f[a[i].t1−1][k]+a[i].w) f [ j ] [ k ] = m a x ( f [ j ] [ k ] , f [ a [ i ] . t 1 − 1 ] [ k ] + a [ i ] . w )
- f[j][k]=max(f[j][k],f[j][a[i].t1−1]+a[i].w) f [ j ] [ k ] = m a x ( f [ j ] [ k ] , f [ j ] [ a [ i ] . t 1 − 1 ] + a [ i ] . w )
- f[j][k]=max(f[j−1][k],f[j][k−1]) f [ j ] [ k ] = m a x ( f [ j − 1 ] [ k ] , f [ j ] [ k − 1 ] )
状态转移方程理解了之后,我们有一个后效性的问题。
我们上面的方程,显然要保证
f[i][j]
f
[
i
]
[
j
]
比
f[k][l]
f
[
k
]
[
l
]
先更新
(i<k且j<l)
(
i
<
k
且
j
<
l
)
这里有个小贪心,直接把所有的魔药根据时间后端点排序就行了。
code
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int num = 0;
char c = ' ';
bool flag = true;
for(;c > '9' || c < '0';c = getchar())
if(c == '-')
flag = false;
for(;c >= '0' && c <= '9';num = num*10+c-48,c=getchar());
return flag ? num : -num;
}
const int maxn=110;
int t,n;
struct node
{
int t1,t2,w;
}a[maxn];
bool mycmp(node a,node b)
{
return a.t2<b.t2;
}
void init()
{
t=read();n=read();
for(int i=1;i<=n;i++)
{
a[i].t1=read();
a[i].t2=read();
a[i].w=read();
}
sort(a+1,a+1+n,mycmp);
}
const int maxt=520;
int f[maxt][maxt];
void DP()
{
for(int i=1;i<=n;i++)
for(int j=t;j>=0;j--)
for(int k=t;k>=0;k--)
{
if(j>=a[i].t2)
f[j][k]=max(f[j][k],f[a[i].t1-1][k]+a[i].w);
if(k>=a[i].t2)
f[j][k]=max(f[j][k],f[j][a[i].t1-1]+a[i].w);
}
printf("%d\n",f[t][t]);
}
int main()
{
init();
DP();
return 0;
}