zoukankan      html  css  js  c++  java
  • Luogu_4644 Cleaning Shifts【题解】最短路代替DP

    题面:https://www.luogu.org/problem/P4644

    和上一篇题解背景基本一样,就是改成了求最小的花费。

    本来应该是通过DP和数据结构优化的。

    但是最小花费好像可以用最短路。

    将每个时间段用自己的价值连边。

    再把每个时间向前一个时间连为0的边。

    这样可以保证最多可以跑N个时间段的边,且合法。

    那么最后假如没有到终点就是失败。

    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxm=300005,maxn=100005;
    int N,M,E;
    struct node{
        int nxt,to;
        ll dis;
        #define nxt(x) e[x].nxt
        #define to(x) e[x].to
        #define dis(x) e[x].dis
    }e[maxm];
    int head[maxm],tot;
    inline void add(int u,int v,int w){
        to(++tot)=v;dis(tot)=(ll)w;
        nxt(tot)=head[u];head[u]=tot;
    }
    ll dis[maxm];
    bool inq[maxm];
    inline void spfa(){
        memset(dis,0x3f,sizeof(dis));
        memset(inq,0,sizeof(inq));
        queue<int> q;
        q.push(M);dis[M]=0;inq[M]=1;
        while(q.size()){
            int now=q.front();q.pop();inq[now]=0;
            for(int i=head[now];i;i=nxt(i)){
                int to=to(i);
                if(dis[to]>dis[now]+dis(i)){
                    dis[to]=dis[now]+dis(i);
                    if(!inq[to]){
                        q.push(to);inq[to]=1;
                    }
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d%d",&N,&M,&E);
        for(int i=M;i<E;i++)
            add(i+1,i,0);
        for(int i=1;i<=N;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(u<M) u=M;
            if(v>E) v=E;
            add(u,v+1,w);
        }
        spfa();
        if(dis[E+1]==0x3f3f3f3f3f3f3f3f) printf("-1
    ");
        else printf("%lld
    ",dis[E+1]);
        return 0;
    }

    那么DP怎么做

    粘了蓝书上的std:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 100006, INF = 0x3f3f3f3f;
    int n, l, r, f[N];
    struct T {
        int l, r, x;
        bool operator < (const T w) const {
            return r < w.r;
        }
    } a[N], t[N<<2];
    
    void build(int p, int l, int r) {
        t[p].l = l;
        t[p].r = r;
        if (l == r) {
            t[p].x = f[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(p << 1, l, mid);
        build(p << 1 | 1, mid + 1, r);
        t[p].x = min(t[p<<1].x, t[p<<1|1].x);
    }
    
    void change(int p, int x, int y) {
        if (t[p].l == t[p].r) {
            t[p].x = y;
            return;
        }
        int mid = (t[p].l + t[p].r) >> 1;
        if (x <= mid) change(p << 1, x, y);
        else change(p << 1 | 1, x, y);
        t[p].x = min(t[p<<1].x, t[p<<1|1].x);
    }
    
    int ask(int p, int l, int r) {
        if (l <= t[p].l && r >= t[p].r) return t[p].x;
        int mid = (t[p].l + t[p].r) / 2, ans = INF;
        if (l <= mid) ans = min(ans, ask(p << 1, l, r));
        if (r > mid) ans = min(ans, ask(p << 1 | 1, l, r));
        return ans;
    }
    
    int main() {
        cin >> n >> l >> r;
        for (int i = 1; i <= n; i++)
            scanf("%d %d %d", &a[i].l, &a[i].r, &a[i].x);
        sort(a + 1, a + n + 1);
        memset(f, 0x3f, sizeof(f));
        f[l] = 0;
        build(1, l, r);
        for (int i = 1; i <= n; i++) {
            f[a[i].r] = min(f[a[i].r], ask(1, a[i].l - 1, a[i].r) + a[i].x);
            change(1, a[i].r, f[a[i].r]);
            if (a[i].r >= r) {
                if (f[a[i].r] == INF) puts("-1");
                else cout << f[a[i].r] << endl;
                return 0;
            }
        }
        return 0;
    }
  • 相关阅读:
    spring-security原理
    win10忘记密码,重置密码
    ELK环境搭建
    Centos8.2安装docker
    pgsql重启
    什么是网站跳出率
    随记
    javascript中apply、call和bind的区别
    Android与Mysql服务器通信
    CentOS 7 最小化安装之后安装Mysql
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11506223.html
Copyright © 2011-2022 走看看