问题 C: 工作(dp)

问题 C: 工作(dp)

题目描述
这次故事的主角是HG!转眼4年过去了,HG本科毕业了,于是找了份工作。每天HG会收到一份任务清单,清单上列出了n个可能需要他完成的任务。每个任务包含3个信息:Ti、Ai、Bi,Ti表示完成此任务需要的时间,Ai表示此任务的到达时间,Bi表示此任务的最晚完成时间。在某一时刻若HG手上没有任务,那么他可以选择一个已经到达且还能够在Bi时刻之前(或者恰好在Bi时刻)完成的任务来做。
由于HG有点懒(纯属虚构:D),他想尽量少的减少他的总工作时间,但是他不能在可以做任务的时候故意不做(这样会被炒鱿鱼的>_<),那么他该如何挑选任务来做呢?
你的任务就是求出HG的最少工作时间(即总共有多少时间HG在做任务)。
输入
第一行一个整数n表示任务数。
以下n行,每行三个整数Ti,Ai,Bi。(n<=1000,0<=Ai,Bi<=1500,Ti>=1)
输出
输出仅一个数,即最少工作时间。
样例输入 Copy
3
15 0 25
50 0 90
45 15 70

 

 

样例输出 Copy
50

 

提示
Ti>=1,0<=Ai,Bi<=1200;
30%的数据满足n<=5;
60%的数据满足n<=500;
100%的数据满足n<=1000。
输入数据保证Bi-Ai要大于等于Ti,且小于2Ti。
思路:dp,起点时间开始到中点时间。dp[i+a[j]]=min(dp[i]+a[j],dp[i+a[j]]);
#pragma comment(linker, "/STACK:1024000000,1024000000")
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;

#define rep(i , a , b) for(register int i=(a);i<=(b);i++)
#define per(i , a , b) for(register int i=(a);i>=(b);i--)
#define ms(s) memset(s, 0, sizeof(s))
#define squ(x) x*x;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int ,int> pi;
typedef unordered_map<int,int> un_map;
template<class T>
inline void read (T &x) {
    x = 0;
    int sign = 1;
    char c = getchar ();
    while (c < '0' || c > '9') {
        if ( c == '-' ) sign = - 1;
        c = getchar ();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar ();
    }
    x = x * sign;
}

const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const ll INF = ll(1e18);
const int mod = 1e9+7;
const double PI = acos(-1);
#define LOCAL

struct node
{
	int t;
	int a,b;
}e[maxn];


int n;
ll dp[maxn];

void solve() {
	int st = inf,ed = -inf;
	rep(i,1,n) {
		read(e[i].t);read(e[i].a);read(e[i].b);
		st=min(st,e[i].a);
		ed=max(ed,e[i].b);
	}
	rep(i,st,ed) dp[i]=inf;
	dp[st]=0;
	rep(i,st,ed) {
		int f=0;
		rep(j,1,n) {
			if(i>=e[j].a&&i+e[j].t<=e[j].b) {
				f=1;
				dp[i+e[j].t]=min(dp[i]+e[j].t,dp[i+e[j].t]);
				//cout<<dp[i+e[j].t]<<' '<<i<<' '<<j<<endl;
			}
		}
		//cout<<dp[i]<<' '<<i<<endl;
		if(!f) dp[i+1]=min(dp[i],dp[i+1]);
	}
	printf("%lld\n", dp[ed]);
}
int main(int argc, char * argv[])
{
    //freopen("/home/yesky/桌面/date.in", "r", stdin);
    //freopen("/home/yesky/桌面/date.out", "w", stdout);
    while(~scanf("%d",&n)) {
    	solve();
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值