BZOJ 1003 ZJOI 2006 物流运输 动态规划+SPFA

来源:互联网 发布:淘宝fgo充值便宜 编辑:程序博客网 时间:2024/05/22 05:09

题目大意:有一些码头由若干条边组成,有些时候有一些码头需要维修,这个期间不能使用这个码头。跟换航线的话会有一定的花费,求规定天数内的最小花费。


思路:最短路方面用SPFA就行,关键是动态规划。这个动规我想了很久,结果到最后发现自己想复杂了。我一开始想的是用SPFA处理出每一个不同的段,然后动规。这样做不仅分段不好分,动规也不好写。之后才发现,一共天数才100,枚举起点和终点才10000,套一个SPFA的O(kn)也不到1qw。。。


CODE:

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 110using namespace std;int days,points,change,edges,asks;int cost[MAX][MAX],used[MAX][MAX];bool v[MAX];int head[MAX],total;int next[MAX << 3],aim[MAX << 3],length[MAX << 3];int f[MAX];bool vis[MAX];int dp[MAX];inline void Add(int x,int y,int len);inline void SPFA();int main(){cin >> days >> points >> change >> edges;for(int x,y,z,i = 1;i <= edges; ++i) {scanf("%d%d%d",&x,&y,&z);Add(x,y,z),Add(y,x,z);}cin >> asks;for(int x,y,z,i = 1;i <= asks; ++i) {scanf("%d%d%d",&z,&x,&y);for(int j = x;j <= y; ++j)used[j][z] = true;}for(int i = 1;i <= days; ++i)for(int j = i;j <= days; ++j) {memset(v,false,sizeof(v));for(int k = i;k <= j; ++k)for(int z = 2;z < points; ++z)if(used[k][z])v[z] = true;SPFA();cost[i][j] = f[points] * (f[points] >= 0x3f3f3f3f ? 1:(j - i + 1));}memset(dp,0x3f,sizeof(dp));dp[0] = 0;for(int i = 1;i <= days; ++i)for(int j = 0;j < i; ++j)dp[i] = min(dp[i],dp[j] + cost[j + 1][i] + change);cout << dp[days] - change << endl;return 0;}inline void Add(int x,int y,int len){next[++total] = head[x];aim[total] = y;length[total] = len;head[x] = total;}inline void SPFA(){static queue<int> q;while(!q.empty())q.pop();memset(f,0x3f,sizeof(f));memset(vis,false,sizeof(vis));q.push(1);f[1] = 0;while(!q.empty()) {int x = q.front(); q.pop();vis[x] = false;for(int i = head[x];i;i = next[i]) {if(v[aim[i]])continue;if(f[aim[i]] > f[x] + length[i]) {f[aim[i]] = f[x] + length[i];if(!vis[aim[i]])vis[aim[i]] = true,q.push(aim[i]);}}}}


0 0
原创粉丝点击