zoukankan      html  css  js  c++  java
  • 1003: [ZJOI2006]物流运输

    题目链接:

    题意:给出n天,m个点,e条边,k是一个改变航线用的花费

    然后给出e条边的信息,有u v w,分别为u到v的长度是w

    然后给出T组输入

    也是三个值,x,l,r表示x港口在l到r天都不能使用

    每天都要从港口1运东西到港口m,问n天的最小花费(修改航道要花费k)

    solve:

    设f[i]为i天的最小花费

    那么就有f[i]=min(f[i],f[j]+(i-j)*dij(j+1,i)+k)这样的递推式

    用f[j]的加上j+1天到i天的最短路径 *天数 +k,枚举这些值找最小的就是i天的最小花费

    不知道有没有人有疑问为什么每次都要加k,不会存在f[j]跟dij(j+1,i)的路线相同吗?  确实的确存在,那为什么要加k?因为如果存在这种情况,那么肯定是前面某个j已经算过了,那么后面更新的+k是不可能小于前面那个值的

    所以任意时候加k对答案的最小值没有影响!!!

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <iostream>
    using namespace std;
    #define ll long long
    #define fi first
    #define se second
    #define re register
    #define pb push_back
    void read(int &a)
    {
        a=0;
        int d=1;
        char ch;
        while(ch=getchar(),ch>'9'||ch<'0')
            if(ch=='-')
                d=-1;
        a=ch-'0';
        while(ch=getchar(),ch>='0'&&ch<='9')
            a=a*10+ch-'0';
        a*=d;
    }
    void write(int x)
    {
        if(x<0)
            putchar(45),x=-x;
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    ll f[105];
    int a[30][30],dis[105];
    int n,m,k,e;
    bool cnt[30][105],vis[30],book[30];
    struct note
    {
        int dis,pos;
        bool operator < (const note &x) const
        {
            return x.dis<dis;
        }
    };
    ll solve(int l,int r)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        dis[1]=0;
        priority_queue <note> q;
        q.push({0,1});
        for(re int i=1;i<=m;i++)
            for(re int j=l;j<=r;j++)
                vis[i]|=cnt[i][j];
        while(!q.empty())
        {
            note p=q.top();q.pop();
            if(vis[p.pos]) continue;
            vis[p.pos]=1;
            for(re int i=1;i<=m;i++)
            {
                if(vis[i]) continue;
                if(dis[i]>dis[p.pos]+a[p.pos][i])
                {
                    dis[i]=dis[p.pos]+a[p.pos][i];
                    if(!vis[i]) q.push({dis[i],i});
                }
            }
        }
        return 1ll*(r-l+1)*dis[m];
    }
    int main()
    {
        read(n),read(m),read(k),read(e);
        memset(a,0x3f,sizeof(a));
        for(re int i=1;i<=e;i++)
        {
            int u,v,w;
            read(u),read(v),read(w);
            a[u][v]=min(a[u][v],w);
            a[v][u]=min(a[v][u],w);
        }
        int T;read(T);
        while(T--)
        {
            int x,l,r;
            read(x),read(l),read(r);
            for(re int i=l;i<=r;i++) cnt[x][i]=true;
        }
        for(re int i=1;i<=n;i++)
        {
            f[i]=solve(1,i);
            for(re int j=2;j<i;j++) f[i]=min(f[i],f[j]+solve(j+1,i)+k);
        }
        printf("%lld
    ",f[n]);
        return 0;
    }
  • 相关阅读:
    MySQL体系结构
    简单高效的代码部署方法
    笔试算法题(07):还原后序遍历数组 & 半翻转英文句段
    笔试算法题(06):最大连续子数组和 & 二叉树路径和值
    笔试算法题(05):转换BST为双向链表 & 查找栈中的最小元素
    笔试算法题(04):实现 string & memcpy & strcpy & strlen
    笔试算法题(03):最小第K个数 & 判定BST后序序列
    笔试算法题(02):N阶阶乘 & 双向循环链表实现
    笔试算法题(01):字符串倒置 & 八皇后问题
    chosen选择框加载数据
  • 原文地址:https://www.cnblogs.com/acm1ruoji/p/12019964.html
Copyright © 2011-2022 走看看