标签:bzoj 最短路 动态规划 zjoi2006 spfa
题目大意:有一些码头由若干条边组成,有些时候有一些码头需要维修,这个期间不能使用这个码头。跟换航线的话会有一定的花费,求规定天数内的最小花费。
思路:最短路方面用SPFA就行,关键是动态规划。这个动规我想了很久,结果到最后发现自己想复杂了。我一开始想的是用SPFA处理出每一个不同的段,然后动规。这样做不仅分段不好分,动规也不好写。之后才发现,一共天数才100,枚举起点和终点才10000,套一个SPFA的O(kn)也不到1qw。。。
CODE:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 110 using 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]); } } } }
BZOJ 1003 ZJOI 2006 物流运输 动态规划+SPFA
标签:bzoj 最短路 动态规划 zjoi2006 spfa
原文地址:http://blog.csdn.net/jiangyuze831/article/details/40295361