• BZOJ.1003.[ZJOI2006]物流运输(DP 最短路Dijkstra)


    题目链接

    容易看出是个最短路+DP。既然答案和天数有关,那么就令(f[i])表示前(i)天最小成本。
    这个转移很好想: (f[i]=min(f[i], f[j]+cost(j+1,i)+K))(cost(j+1,i))即第(j+1)天到第(i)天(使用同一道路)所需花费,即最短路,这个可以预处理出来。
    注意是否可行的判断。

    //880kb	88ms
    //好像很吉利啊 
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    #define pr std::pair<int,int>
    #define mp std::make_pair
    const int N=23,M=900,INF=0x3f3f3f3f;//边数n*n啊。。
    
    int d,n,K,m,Enum,H[N],nxt[M],to[M],len[M],cost[102][102],dis[N],f[102];
    bool vis[N],can_t[N][102];
    std::priority_queue<pr> q;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    inline void AddEdge(int u,int v,int w)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w;
    }
    inline bool Judge(int x,int u,int v){
    //	return st[x]>v||ed[x]<u;//WA:可能有多段!有毒!
    	for(int i=u; i<=v; ++i) if(can_t[x][i]) return 0;
    	return 1;
    }
    int Dijkstra(int a,int b)
    {
    	memset(vis,0,sizeof vis);
    	memset(dis,0x3f,sizeof dis);
    	while(!q.empty()) q.pop();
    	dis[1]=0, q.push(mp(0,1));
    	while(!q.empty())
    	{
    		int x=q.top().second;q.pop();
    		if(x==n) return dis[n]*(b-a+1);
    		if(vis[x]) continue;
    		vis[x]=1;
    		for(int v,i=H[x]; i; i=nxt[i])
    			if(!vis[v=to[i]] && Judge(v,a,b) && dis[v]>dis[x]+len[i])
    				dis[v]=dis[x]+len[i], q.push(mp(-dis[v],v));
    	}
    	return INF;
    }
    
    int main()
    {
    	d=read(),n=read(),K=read(),m=read();
    	int u,v;
    	while(m--) u=read(),v=read(),AddEdge(u,v,read());
    	int t=read(),p;
    	while(t--){
    		p=read(),u=read(),v=read();
    		for(int i=u; i<=v; ++i) can_t[p][i]=1;
    	}
    	for(int i=1; i<=d; ++i)
    		for(int j=i; j<=d; ++j)
    		{
    			cost[i][j]=Dijkstra(i,j);
    			if(cost[i][j]==INF){
    				for(int k=j+1; k<=d; ++k) cost[i][k]=INF;
    				break;
    			}
    		}
    	for(int i=1; i<=d; ++i) f[i]=cost[1][i];
    	for(int i=2; i<=d; ++i)
    		for(int j=i-1; j; --j)
    			if(cost[j+1][i]<INF)//注意INF的判断。
    				f[i]=std::min(f[i],f[j]+cost[j+1][i]+K);
    			else break;
    	printf("%d",f[d]);
    
    	return 0;
    }
    
  • 相关阅读:
    利用ssh的私钥登录Linux server
    PSR-2 代码风格规范
    MySQL的四种事务隔离级别
    table添加横向滚动条
    转换图片大小
    百度地图Label 样式:label.setStyle
    鼠标的几种常用样式
    百度地图API-自定义图标覆盖物
    微信公众号自定义菜单中可加入的表情
    微信公众号项目总结
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8757280.html
Copyright © 2020-2023  润新知