看了这里 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. Ajax效果

    Ajax的效果就是不通过网页的跳转,就可以通过请求,就可以自动加载某个网页,在注册帐号时,经常 不通过网页跳转从数据库中查看是否有相同数据的出现,确认是否能够正确注册 下面是用其他方式实现ajax的效 ...

  2. orcale授权

    grant connect,resource,dba to 表名;--用户授权 CONNECT角色: --是授予最终用户的典型权利,最基本的 CREATE SESSION --建立会话 RESOURC ...

  3. scala学习笔记:理解lazy值

    scala> var counter = 0 counter: Int = 0 scala> def foo = {counter += 1; counter} foo: Int scal ...

  4. Spring的servlet context和application context

    Spring lets you define multiple contexts in a parent-child hierarchy. The applicationContext.xml def ...

  5. Android Studio依赖dependencies和Eclipse加上lib包解决重复编译某些项目的问题

    android运行时编译,可以在android的dependencies里面加语句, 一般是compile 'com.android.support:appcompat-v7:22.2.1' comp ...

  6. ACM——Quicksum

    Quicksum 时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte总提交:615            测试通过:256 描述 A chec ...

  7. sqlserver中的聚合函数

    聚合函数:就是按照一定的规则将多行(Row)数据汇总成一行的函数,对数据进行汇总前,还可以按特定的列(coloumn)将数据进行分组(group by)再汇总,然后按照再次给定的条件进行筛选 一:Co ...

  8. 2013年全国各大著名的IT公司薪资待遇大揭密

    以下为转载,特此说明!--西电好网 ============================================ 1: 本人西电通院2013届毕业硕士,根据今年找工作的情况以及身边同学的汇 ...

  9. C#与C++相比较之STL篇(续一)

    本篇接<C#与C++相比较之STL篇>,主要探索C++STL的两个组件:算法和仿函数,以及C#的linq和拉姆达表达式.委托. STL的算法与仿函数 算法是个庞大的主题,STL包含了超过1 ...

  10. linksys wrt160nv3 刷dd-wrt固件

    家中有个闲置的wrt160nv3路由器,无意中在网上发现可以刷dd-wrt固件来实现更多功能.目前家里电信光猫F460的自带无线使用起来不是很稳定,就想把wrt160nv3刷成dd-wrt来当做一个A ...