看了这里 http://blog.csdn.net/acm_cxlove/article/details/8679230的分析之后自己又按照自己的模板写了一遍,算是对spfa又加深了一步认识(以前真是只会用,没想太多)。

又来当一次搬运工,一点点进步。

题意是这样的:A个村庄,B个城堡,共有K次穿越的机会,且不能经过城堡或者穿越距离必须不超过L,否则必须停下来,当然,不能再道路中间停下来。

按照大大的思路是这样做的:对于每出队的一个结点u,均有两种方式继续走下去,一中是使用一次穿越,另一种是不使用。这样对于使用穿越的情况,必须考虑所有满足d[u][v]<=L的点v,然后dp[v][k+1] = min(dp[v][k+1],dp[u][k])转移方程,其中dp[u][k]表示从起点A+B走到u使用k次穿越经过的最小距离;对于不使用穿越的情况就和普通spfa一样转移。

然后怎样判断由一个节点到另一个节点能够满足d[u][v]<=L呢,这中间会涉及到城堡不能穿越,可以求出使用spfa求出(i,j)之间的最短距离,对于j是城堡的时候就不把j入队,这样中间有城堡的两个节点d[i][j]是不能直接穿越的,也就是d[i][j] == inf.

然后下面是我写的代码:

(思路也可以去原po那里看)

 #include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pb push_back
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<int>:: iterator IT;
#define N 2000
#define INF 200000
struct EDGE
{
int i, c;
EDGE *ani,*next;
} *Edge[N], E[INF];
int d[N][N], inq[N], dp[N][];
int cnt, A, B, M, L, K;
void add(int i, int j, int c, EDGE &e1, EDGE &e2)
{
e1.i = j, e1.c = c, e1.ani = &e2, e1.next = Edge[i], Edge[i] = &e1;
e2.i = i, e2.c = c, e2.ani = &e1, e2.next = Edge[j], Edge[j] = &e2;
cnt += ;
}
void init(void)
{
cnt = ;
memset(Edge, , sizeof(Edge));
// memset(d, 0x0f, sizeof(d));
}
void preprocess(void)
{
memset(d, 0x3f, sizeof(d));
for(int i = ; i <= A + B; i++)
{
queue<int> q;
memset(inq, , sizeof(inq));
inq[i] = ;
d[i][i] = ;
q.push(i);
while(!q.empty())
{
int u = q.front();
int v;
q.pop();
inq[u] = ;
for(EDGE * p = Edge[u]; p; p = p->next)
if(d[i][v = p->i] > d[i][u] + p->c)
{
if(d[i][v] = d[i][u] + p->c, v <= A && !inq[v])
inq[v] = , q.push(v);
}
}
}
}
void spfa(int s, int end)
{
memset(dp, 0x3f, sizeof(dp));
memset(inq, , sizeof(inq));
queue<int> q;
inq[s] = ;
dp[s][] = ;
q.push(s);
while(!q.empty())
{
int u = q.front(), v;
q.pop();
inq[u] = ;
for(EDGE *p = Edge[u]; p; p = p->next)
for(int k = ; k <= K; k++)
if(dp[u][k] < inf)
{
if(dp[v = p->i][k] > dp[u][k] + p->c)
if(dp[v][k] = dp[u][k] + p->c, !inq[v])
inq[v] = , q.push(v);
if(k - K)
{
for(v = ; v <= A + B; v++)
// if(dp[u][k] < inf)
if(d[u][v] <= L && dp[u][k] < dp[v][k+])
if(dp[v][k+] = dp[u][k], !inq[v])
inq[v] = , q.push(v);
}
}
}
}
int main(void)
{ int T;
for(int t = scanf("%d", &T); t <= T; t++)
{
init();
scanf("%d%d%d%d%d", &A, &B, &M, &L, &K);
for(int i = ; i <= M; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w, E[cnt], E[cnt + ]);
}
preprocess();
spfa(A+B, );
int ans = inf;
for(int k = ; k <= K; k++)
ans = min(dp[][k], ans);
printf("%d\n", ans);
}
return ;
}

UVA 10269 Adventure of Super Mario的更多相关文章

  1. UVa 10269 Adventure of Super Mario (Floyd + DP + BFS)

    题意:有A个村庄,B个城市,m条边,从起点到终点,找一条最短路径.但是,有一种工具可以使人不费力的移动L个长度,但始末点必须是城市或村庄.这种工具有k个,每个只能使用一次,并且在城市内部不可使用,但在 ...

  2. UVA10269 Adventure of Super Mario(Floyd+DP)

    UVA10269 Adventure of Super Mario(Floyd+DP) After rescuing the beautiful princess, Super Mario needs ...

  3. ZOJ1232 Adventure of Super Mario(DP+SPFA)

    dp[u][t]表示从起点出发,到达i点且用了t次magic boot时的最短时间, 方程如下: dp[v][t]=min(dp[v][t],dp[u][t]+dis[u][v]); dp[v][t] ...

  4. ZOJ1232 Adventure of Super Mario spfa上的dp

    很早之前听说有一种dp是在图上的dp,然后是在跑SPFA的时候进行dp,所以特地找了一题关于在SPFA的时候dp的. 题意:1~a是村庄 a+1~a+b是城堡,存在m条无向边.求由a+b->1的 ...

  5. UVA-10269 Adventure of Super Mario (dijkstra)

    题目大意:有A个村庄,B个城市,m条边,从起点到终点,找一条最短路径.但是,有一种工具可以使人不费力的移动L个长度,但始末点必须是城市或村庄.这种工具有k个,每个只能使用一次,并且在城市内部不可使用, ...

  6. ZOJ 1232 Adventure of Super Mario (Floyd + DP)

    题意:有a个村庄,编号为1到a,有b个城堡,编号为a+1到a+b.现在超级玛丽在a+b处,他的家在1处.每条路是双向的,两端地点的编号以及路的长度都已给出.路的长度和通过所需时间相等.他有一双鞋子,可 ...

  7. [题解]UVA10269 Adventure of Super Mario

    链接:http://vjudge.net/problem/viewProblem.action?id=24902 描述:由城镇.村子和双向边组成的图,从A+B走到1,要求最短路.有K次瞬移的机会,距离 ...

  8. zoj1232Adventure of Super Mario(图上dp)

    题目连接: 啊哈哈.点我点我 思路: 这个题目是一个图上dp问题.先floyd预处理出图上全部点的最短路,可是在floyd的时候,把可以用神器的地方预处理出来,也就是转折点地方不能为城堡..预处理完成 ...

  9. HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

随机推荐

  1. Bootstrap--全局css样式之图片

    好久没有更新博客了,在这里跟大家分享一下生活的小乐趣,作为程序员,整天对着电脑是很不爽的,加班也是常有的,所以连续工作对身体是很不爽的,而且随着年龄的增加,程序员身体状况会越来越差,还是建议大家要常去 ...

  2. ASP中双引号单引号和&连接符使用技巧

    ASP中双引号单引号和&连接符使用技巧 一.ASP中处在双引号中的可以是任意的字符.字符串,HTML代码 1.<%response.write ("I am here" ...

  3. MFC多视图共用一文档实现

    项目过程中有定制视图的需求,具体为打开程序默认双视图并且共用一个文档.在网上找了许多类似的资料,都不尽完善.本文直接从达到目的的角度叙述,实现原理不再多说. 1.在自己的App类中定义public变量 ...

  4. 如何在Windows系统上用抓包软件Wireshark截获iPhone等网络通讯数据

    http://www.jb51.net/os/windows/189090.html 今天给大家介绍一种如何在Windows操作系统上使用著名的抓包工具软件Wireshark来截获iPhone.iPa ...

  5. HW--漂亮度2(测试通过)

    总结:几个函数的使用 (1)  int num=Integer.parseInt(str[0]); //将第一个字符串转成整形数,表示名字个数 (2) String string1=str[i].to ...

  6. OJ——华为编程题目:输入字符串括号是否匹配

    package t0815; /* * 华为编程题目:输入字符串括号是否匹配 * 若都匹配输出为0,否则为1 * 样例输入:Terminal user [name | number (1)] * 样例 ...

  7. java集合框架示例图

  8. CheckSum

    1.What is Checksum? A check sum is basically a value that is computed from data packet to check its ...

  9. 2015/7/6 (!长期更新!)C语言从零——张呵呵

    随即呈上! By    He_He _S 小组 @成都七中高新OI2015

  10. 构造函数为什么不能是虚函数 ( 转载自C/C++程序员之家)

    从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的.问题出来了,如果构造函数是虚的,就需要通过 vtable来调用, ...