bzoj1003

来源:互联网 发布:种子软件哪个好 编辑:程序博客网 时间:2024/06/05 16:20

这道题一看到之后,第一感觉就是:最短路???但是贪心肯定是不行de

偷偷告诉你们一个经验,当你做题时,第一印象想到贪心,但这题显然不能贪心,多半正解是dp

那怎么更新呢?我们知道,如果存在某种走法虽然代价十分小,但适用范围很窄,照样说明不了什么

于是我们存储一段时间中都可以适用的那条最短路径(虽然可能会没有)

然后就去dp就好啦~

#include <cstdio>#include <queue>#include <algorithm>#include <cstring>using namespace std;#define M 24#define N 110struct EDGE {int to, val, next;}edge[M*M];struct IMPORTANT {int num, a[M];}p[N];bool v[M], flag[M];int cost[N][N], head[M], dis[M], f[N];int n, m, k, e, cnt, s;inline void add(int x, int y, int z) {edge[++cnt].to = y; edge[cnt].val = z;edge[cnt].next = head[x]; head[x] = cnt;return ;}inline int spfa(int x, int y) {memset(v, false, sizeof(v));for(int i = x; i <= y; ++i)for(int j = 1; j <= p[i].num; ++j)v[p[i].a[j]] = true;queue<int>Q;memset(flag, false, sizeof(flag));Q.push(1); memset(dis, 127, sizeof(dis)); dis[1] = 0;flag[1] = true; while(!Q.empty()) {int now = Q.front(); Q.pop(); flag[now] = false;for(int i = head[now]; i; i = edge[i].next) {int to = edge[i].to, val = edge[i].val;if(v[to]) continue;if(dis[now] + val < dis[to]) {dis[to] = dis[now] + val;if(!flag[to]) {Q.push(to); flag[to] = true;}}}}return dis[m];}int main() {freopen("1003.in", "r", stdin);scanf("%d%d%d%d", &n, &m, &k, &e);memset(head, 0, sizeof(head)); cnt = 0;for(int i = 1; i <= e; ++i) {int u, v, w;scanf("%d%d%d", &u, &v, &w);add(u, v, w); add(v, u, w);}scanf("%d", &s); memset(p, 0, sizeof(p));for(int i = 1; i <= s; ++i) {int ai, fr, to;scanf("%d%d%d", &ai, &fr, &to);for(int j = fr; j <= to; ++j) {p[j].num++;p[j].a[p[j].num] = ai;}}for(int i = 1; i <= n; ++i)for(int j = i; j <= n; ++j) {cost[i][j] = spfa(i, j);if(cost[i][j] <= 999999999) cost[i][j]*= (j - i + 1);}for(int i = 1; i <= n; ++i) f[i] = cost[1][i];for(int i = 2; i <= n; ++i) {for(int j = 1; j < i; ++j) f[i] = min(f[i], f[j] + cost[j + 1][i] + k);}printf("%d", f[n]);return 0;}


原创粉丝点击