其他分享
首页 > 其他分享> > 尼克的任务

尼克的任务

作者:互联网

传送门

题目描述:时间1-n范围内,有k个任务,起始和终止时间固定,员工在空闲时如果有任务就必须工作,

但是如果有多个任务就可以自己选择,求最大休闲时间.

思路:

方法1:dp倒着推,dp[i]表示在i时间点开始工作的最大休闲时间,

如果i是某些工作的起始点,则必须要工作,从这些工作中的终止时间t中找最小的工作时间,

dp[i]=min(dp[i],dp[t]+t-i);

如果i不是工作的起始点,则dp[i]=dp[i+1],即这一分钟不需要工作

输出dp[1]即可

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100100;
const int inf = 0x3f3f3f3f;
typedef long long ll;
vector<int>work[maxn];
int f[maxn];
int n, k;
int main() {
    //freopen("test.txt", "r", stdin);
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= k; i++) {
        int s, t; scanf("%d%d", &s, &t);
        work[s].push_back(t);
    }
    memset(f, 0x3f, sizeof(f));
    f[n+1] = 0;
    for (int i = n; i >= 1; i--) {
        if (work[i].empty()) {//没有工作
            f[i] = f[i + 1];
        }
        else {//有工作必须要开始工作
            for (int x : work[i]) {
                f[i] = min(f[i], f[i + x] + x);
            }
        }
    }
    //总时长-最小工作时间
    cout << n-f[1] << endl;
    return 0;
}

 方法2,最短路

我们把没一分钟看作一个点,工作时间就是起点与重点连边,权值为时间,

如果该点没有工作,则可以休息,与下一个点连权值为0的边,跑1-n的最短路即可得到最小工作时间t

n-t就是最长休息时间

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100100;
const int inf = 0x3f3f3f3f;
//之前少开了个0...
typedef long long ll;
struct edge {
    int f, t, dis, nxt;
}e[maxn];
int hd[maxn], tot;
void add(int f, int t, int dis) {
    e[++tot] = { f,t,dis,hd[f] };
    hd[f] = tot;
}
int n, k;
int dis[maxn], inque[maxn];
void spfa(int s) {
    queue<int>q;
    memset(dis, 0x3f, sizeof(dis));
    dis[s] = 0;
    q.push(s);
    inque[s] = 1;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        inque[u] = 0;
        for (int i = hd[u]; i; i = e[i].nxt) {
            int v = e[i].t;
            if (dis[u] + e[i].dis < dis[v]) {
                dis[v] = dis[u] + e[i].dis;
                if (!inque[v]) {
                    q.push(v);
                    inque[v] = 1;
                }
            }
        }
    }
}
int main() {
    //freopen("test.txt", "r", stdin);
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= k; i++) {
        int s, t; scanf("%d%d", &s, &t);
        add(s, s + t, t);
    }
    for (int i = 1; i <= n; i++) {
        if (!hd[i]) {//该点不需要工作
            add(i, i + 1, 0);
        }
    }
    spfa(1);
    cout << n - dis[n + 1] << endl;
    return 0;
}

 

标签:int,inque,工作,任务,maxn,尼克,dp,dis
来源: https://www.cnblogs.com/MYMYACMer/p/14798036.html