看了这里 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. C# 批量插入表SQLSERVER SqlBulkCopy往数据库中批量插入数据

    #region 帮助实例:SQL 批量插入数据 多种方法 /// <summary> /// SqlBulkCopy往数据库中批量插入数据 /// </summary> /// ...

  2. Android中FTP服务器搭建入门

    http://www.2cto.com/kf/201501/374048.html http://blog.csdn.net/smile3670/article/details/44343617  有 ...

  3. MYSQL数据库间同步数据

    http://blog.csdn.net/swandy45/article/details/6982421 环境要求: Windows 操作系统 需要Mysql 3.23.15以后的版本. 假设数据库 ...

  4. ubuntu系统下wireshark普通用户抓包设置

    dumpcap需要root权限才能使用的,以普通用户打开Wireshark,Wireshark当然没有权限使用dumpcap进行截取封包.   虽然可以使用    sudo wireshark    ...

  5. $.get

    $('#choice').change(function() { if($(this).val() != '') { $.get( 'data.php', { what: $(this).val() ...

  6. mac 查看系统时区

    sudo systemsetup -gettimezone https://developer.apple.com/library/mac/documentation/Darwin/Reference ...

  7. sea.js总结

    SeaJS是一个遵循CommonJS规范的JavaScript模块加载框架. 参考以下网址进行详细学习: https://segmentfault.com/a/1190000000357191?pag ...

  8. 01_Java解析XML

    [打印list.Map集合的工具方法] /** * 打印List集合对应的元素 */ public void printList(List<Object> list){ for(Objec ...

  9. JDBC访问SQLServer2008数据库

    来源:十二随风博客 由JDBC驱动直接访问数据库优点:100% Java,快又可跨平台缺点:访问不同的数据库需要下载专用的JDBC驱动 (1)下载对应数据库版本的jdbc驱动并安装,注意安装后的得到的 ...

  10. lamp环境centos5.10,phpprotobuf模块安装,及简单应用

    ==相关参考== rpm包 http://rpmfind.net/linux/rpm2html/ Linux rpm 命令参数使用详解[介绍和应用] phpize学习 http://blog.sina ...