BZOJ 1003 物流运输【最短路】【动态规划】

这道题数据太小啦!先枚举i,j表示从第i天到第j天不更改航线的费用。

然后直接跑最短路算法(我用的是Q版男朋友算法)

动归方程显然是f[i] = min(f[i], f[j] + cost[j+1][i] + k)

(PS:这道题一开始看成了某航线是否被ban...大家要注意啊!还有n和m的问题,各种别扭...)

代码(Submit Time 2016-01-10 15:48:24

#include <cstdio>
#include <deque>
using namespace std;
const int maxd = 105;
const int maxn = 25;
const int INF = 1000000007;
int d, n, k, m, q;
int cost[maxd][maxd];
int f[maxd];
bool ban[maxn * maxn][maxd];
bool ava[maxd];
int min(int a, int b) {
	return a < b ? a : b;
}
int getint() {
	int r = 0, k = 1;
	char c;
	for (c = getchar(); c < '0' || c > '9'; c = getchar() ) if (c == '-') k = -1;
	for (; '0' <= c && c <= '9'; c = getchar() ) r = r * 10 - '0' + c;
	return r * k;
}
struct edge_type {
	int v, next, w;
} edge[maxn * maxn]; int cnte = 0, h[maxn];
void ins(int u, int v, int w) {
	edge[++cnte].v = v;
	edge[cnte].w = w;
	edge[cnte].next = h[u];
	h[u] = cnte;
}
deque<int> Q;
int dis[maxn];
bool inque[maxn];
void SPFA() {
	Q.push_back(1);
	dis[1] = 0;
	inque[1] = true;
	for (int i = 2; i <= n; ++i) dis[i] = INF;
	int now;
	while (!Q.empty()) {
		now = Q.front(); Q.pop_front(); inque[now] = false;
		for (int i = h[now]; i; i = edge[i].next) {
			int v = edge[i].v;
			if (!ava[v]) continue;
			if (dis[v] > dis[now] + edge[i].w) {
				dis[v] = dis[now] + edge[i].w;
				if (!inque[v]) {
					Q.push_back(v);
					inque[v] = true;
				}
			}
		}
	}
}
int main() {
	d = getint(); n = getint(); k = getint(); m = getint();
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		u = getint(); v = getint(); w = getint();
		ins(u, v, w); ins(v, u, w);
	}
	q = getint();
	for (int i = 0; i < q; ++i) {
		u = getint(); v = getint(); w = getint();
		for (int j = v; j <= w; ++j) ban[u][j] = true;
	}
	for (int i = 1; i <= d; ++i)
		for (int j = i; j <= d; ++j)
		{
			for (int mt = 1; mt <= n; ++mt) {
				ava[mt] = true;
				for (int t = i; t <= j; ++t)
					if (ban[mt][t]) {
						ava[mt] = false;
						break;
					}
			}
			SPFA();
			if (dis[n] == INF) cost[i][j] = INF;
			else cost[i][j] = dis[n] * (j-i+1);
		}
	for (int i = 1; i <= d; ++i) {
		f[i] = cost[1][i];
		for (int j = 1; j <= i; ++j) f[i] = min(f[i], f[j] + cost[j+1][i] + k);
	}
	printf("%d\n", f[d]);
	return 0;
}


posted on 2016-01-10 15:15  MagHSK  阅读(119)  评论(0编辑  收藏  举报