RQNOJ 99 配置魔药
题目描述
传送门
在《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)。
输出格式
输出文件medic.out只有一行,只输出一个正整数,即为最大药效。
样例
Input
7 4
1 2 10
4 7 20
1 3 2
3 7 3
Output
35
主要思路
此题可化简为选取线段的题目:即选取多条线段,任意两条线段不能有重合,求最大的分值。但此题由于有两个锅,所以较为麻烦。我的解决方法是:开一个三维dp数组,dp[k][i][j],描述选到第k个魔药,第一个锅在配第i种魔药,第二个锅在配第j种魔药时的最大分值(药效)。当转移第一个锅时,前两维相同,第二个锅时,第一维和第三维相同,这样就不会有重复,每次更新答案即可。转移过程如下:
此题与另一道题(RQNOJ 569 Milking Time)相比,更多了一层难度,对于选取线段的题目基础知识的讲解,欢迎来看我的另一篇博客:RQNOJ 569 Milking Time
代码如下
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <map>
#include <stack>
#include <cstring>
using namespace std;
#define ll long long
struct nod{
int l,r,w;
}a[105];
int t,n,ans;
int dp[105][105][105];
bool cmp(nod x,nod y)
{
return x.l<y.l;
}
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
cin>>t>>n;
for(int i=1;i<=n;i++)
cin>>a[i].l>>a[i].r>>a[i].w;
sort(a+1,a+n+1,cmp);
for(int k=1;k<=n;k++)
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
{
dp[k][i][j]=dp[k-1][i][j];
if(a[i].r<a[k].l)
dp[k][k][j]=max(dp[k][k][j],dp[k-1][i][j]+a[k].w);
if(a[j].r<a[k].l)
dp[k][i][k]=max(dp[k][i][k],dp[k-1][i][j]+a[k].w);
ans=max(ans,max(dp[k][k][j],dp[k][i][k]));
}
cout<<ans<<endl;
return 0;
}