题意:
有一个懒工人,他要完成n个任务。每个任务都需要花费时间ti并且在[ai,bi]这个时间范围内完成。对于某个时间点如果有工作可以完成,那么他必须选择一个来完成,工作一旦开始就不能被打断。当然这个工人很懒,所以他希望他工作的时间越短越好。
解题思路:
首先我们可以预处理处对于某个时间点,工人可以完成的任务有哪些。当一个任务在时间点t满足 ai <= t && t + ti <= bi时就说明该任务可以在时间点t完成。
这样预处理后就很容易想用DP来解决此问题了。用dp[t] 表示从时间点t开始的最少工作时间。如果有任务可以做 那么就由做了这个任务之后的状态来跟新 dp[t] = min(dp[t], dp[t+ti] + ti); 否则就有 dp[t] = dp[t+1];这样从后往前dp一遍就得到解了。
//by dreameracm
#include <cstdio>
#include <algorithm>
#include <vector>
#define INF 1<<30
using namespace std;
struct node
{
int x,y,z;
};
node p[1005];
vector<int> can[500];
int dp[500];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
int mint=1000,maxt=0;
scanf("%d",&n);
for (int i = 0; i < n; i++)
{
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
mint=min(mint,p[i].y);//更新最小时间
maxt=max(maxt,p[i].z);//更新最大时间
}
for (int i = mint; i < maxt; i++)
{
can[i].clear();
for (int j = 0; j < n; j++)
{
if (p[j].y<=i && i + p[j].x <= p[j].z)//计算每个时间点可以做的任务
{
can[i].push_back(j);
}
}
}
dp[maxt] = 0;//初始化最大时间的解
for (int i = maxt-1; i >= mint; i--)
{
if(can[i].empty())//没有任务可以做时的情况
{
dp[i] = dp[i+1];
}
else
{
dp[i] = INF;
for (int j = 0; j < (int)can[i].size(); j++)//用法每一个任务更新dp[i]的值
{
dp[i] = min(dp[i],dp[i+p[can[i][j]].x]+p[can[i][j]].x);
}
}
}
printf("%d\n",dp[mint]);
}
return 0;
}