bzoj 1003物流运输 区间dp+spfa

基本思路:

一开始确实没什么思路,因为觉得怎么着都会超时,然后看一下数据范围,呵,怎么都不会超时。

思路:

1.看到能改变线路,想到可以用以下区间dp,区间dp的话,先枚举长度,枚举开始位置,然后枚举中间点 dp[i][j]=min(dp[i][j],dp[i][z]+dp[z][j]+k);

2.然后每段时间最短路究竟是多少,然后因为不会超时,所以就二重循环枚举就好了

(ps:这里要说明一下给自己提个醒:

  spfa就是队列优化的迪杰斯特拉,然后的话vis数组每次出一个就置零一个,如果不置零是错的

  堆优化的迪杰斯特拉自己之前也加vis,而且每次出一个的话不置零,不会错,因为vis数组是不必要的

  所以以后写的话一般就写spfa好了,堆优化的迪杰斯特拉的话略难写一点,而且两者速度也差不多

  普通的迪杰斯特拉的话还是要置零的,因为比起spfa就是优化在了队列

代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<algorithm>
#include<queue>

using namespace std;

typedef long long ll;

const int inf = 0x3f3f3f3f;
const int maxn = 100+10;

int head[maxn],cnt;
struct Edge{
    int to,val,next;
}edge[maxn<<4];
ll tim[maxn][maxn],f[maxn][maxn];
bool flag[maxn][maxn],block[maxn],vis[maxn];
int dis[maxn];
int n,m,k;

void add(int u,int v,int w){
    edge[cnt].to=v;
    edge[cnt].val=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int spfa(int s,int e){
    memset(block,false,sizeof(block));
    memset(vis,false,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    queue<int>q;
    q.push(1);vis[1]=true;dis[1]=0;
    for(int i=s;i<=e;i++){
        for(int j=1;j<=m;j++){
            if(flag[i][j]){
                block[j]=true;
            }
        }
    }
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            int w=edge[i].val;
            if(!block[v]&&dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                if(!vis[v]){
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
        vis[u]=false;
    }
    return dis[m];
}
void dp(){
    for(int l=1;l<=n;l++){
        for(int s=1;s<=n;s++){
            int e=s+l-1;
            if(e>n) continue;
            f[s][e]=(ll)tim[s][e]*(e-s+1);
            for(int z=s;z<e;z++){
                f[s][e]=min(f[s][e],f[s][z]+k+f[z+1][e]);
            }
        }
    }
}
int main(){
    memset(head,-1,sizeof(head));cnt=0;
    int p;
    scanf("%d%d%d%d",&n,&m,&k,&p);
    for(int i=1;i<=p;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);add(v,u,w);
    }
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        int id,u,v;
        scanf("%d%d%d",&id,&u,&v);
        for(int j=u;j<=v;j++){
            flag[j][id]=true;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j++){
            tim[i][j]=spfa(i,j);
        }
    }
    dp();
    cout<<f[1][n]<<endl;
    return 0;
}

  

原文地址:https://www.cnblogs.com/imzscilovecode/p/8974488.html

时间: 2024-08-10 23:30:59

bzoj 1003物流运输 区间dp+spfa的相关文章

BZOJ 1003 物流运输trans(最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1003 思路:m个点e条边n天.给出每条边的权值以及有些点有些天不能走.对于某连续的两天i和i+1,若两天从起点到终点选择的路径不同需要额外代价K.求最小的总代价:ans=sum(每天的代价)+K*改变的次数.每天的代价定义为这一天s到t选择的路径的长度. 思路:令cost[i][j]表示从第i天 到第j天选择一条路径的最短路,f[i]表示前i天的总代价,则f[i]=min(f[j]+c

BZOJ 1003 物流运输 (动态规划 SPFA 最短路)

1003: [ZJOI2006]物流运输 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 5590 Solved: 2293 [Submit][Status][Discuss] Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完. 货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线, 以便对整个运输过程实施严格的管理和跟踪.由于各种因素的存在,有的时候某个 码头会无法装卸货物.这

BZOJ 1003 物流运输trans dijstra+dp

1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3896  Solved: 1608[Submit][Status][Discuss] Description 物 流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路 线,以便对整个运输过程实施严格的管理和跟踪.由于各种因素的存在,有的时候某个码头会无法装卸

BZOJ 1003 物流运输 (dp + dijkstra)

1003: [ZJOI2006]物流运输 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8672  Solved: 3678[Submit][Status][Discuss] Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪.由于各种因素的存在,有的时候某个码头会无法装卸货物.这时候就

BZOJ 1003 物流运输trans

Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪.由于各种因素的存在,有的时候某个码头会无法装卸货物.这时候就必须修改运输路线,让货物能够按时到达目的地.但是修改路线是一件十分麻烦的事情,会带来额外的成本.因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小. Input 第一行是四个整数n(1<=n<=100).m(1&

[BZOJ]1003 物流运输(ZJOI2006)

挖坑,日常划水. 从BZOJ上的AC人数来看这题确实不难,但做这种题的常见思路让小C决定还是mark一下. Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪.由于各种因素的存在,有的时候某个码头会无法装卸货物.这时候就必须修改运输路线,让货物能够按时到达目的地.但是修改路线是一件十分麻烦的事情,会带来额外的成本.因此物流公司希望能够订

BZOJ 1003 物流运输 长歌当哭!

真是很生气啊!这道题简直整整花了我一天的时间.自己怎么这么弱呢? 算了,还是来聊一聊这道题的解题历程吧!一开始打算枚举从起点到终点的每条路径后再去动态规划.的确一开始的版本就是这样的.结果TLE了.之后打算再次版本上再去优化,曾想过把map改成数组,把深搜改成dijkstra,还打算把动态数组改成数组,由于一开始的动态规划是按照每一天推到下一天的,所以也曾把这个改成一个区间去推.但是最终在多次TLE后,我换回了WA.内心无比悲痛.无奈之下,跑去看了别人的题解,我去,这么简单.算了,真的得加把劲,

BZOJ 1003 物流运输

最短路+dp. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxd 150 #define maxv 250 #define maxe 50050 #define inf 1000000007 using namespace std; struct edge { long long v,w,nx

BZOJ 1055 玩具取名(区间DP)

很显然的区间DP,定义dp[i][j][k], 如果dp[i][j][k]=1表示字符串[i,j]可以组成k字符. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map>