HDU 1142 SPFA + DFS记忆搜索 学习了!!

来源:互联网 发布:redhat7 yum源配置 编辑:程序博客网 时间:2024/05/21 19:30

走AB这条路的前提是: B到home的最短路比A到home的最短路要短,求满足这个要求的office到home的路有多少条

SPFA:参考http://sgeteternal.iteye.com/blog/1148891

spfa比dijkstra极大程度减少不必要的松弛操作。故而比dij快。

#include <iostream>#include <vector>#include <cstdio>#include <cstdlib>#include <queue>#include <memory.h>using namespace std;#define MAXI 1011#define INFI 0x7fffffff#define LLD long longstruct V{int v, w;//v, w[u, v]};vector<V> g[MAXI]; //邻接表int n, dis[MAXI];//|V|, d[]bool inQ[MAXI];//入队标记void SPFA(int u)//源点{int i, v, w;queue<int> Q;//队列for (i = 0; i < n; i++)//初始化{dis[i] = INFI;inQ[i] = false;}Q.push(u);//压入源点inQ[u] = true;dis[u] = 0;while (!Q.empty())//队列不为空{u = Q.front();Q.pop();inQ[u] = false;for (i = 0; i < g[u].size(); i++){v = g[u][i].v;w = g[u][i].w;if (dis[v] - w > dis[u])//符合三角不等式2{dis[v] = w + dis[u];//松弛操作if (inQ[v] == false)//判断v系唔系队列{Q.push(v);//唔系就入队列inQ[v] = true;}}}}}

所以SPFA其实就是大家熟悉的 bfs + 松弛操作

松弛操作:应该就是判断更新。

负回路版本只需要加上一个数组记录每个点入队次数就得。

 记忆化搜索:算法上依然是搜索的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存。
一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。
更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。
记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,
以后再次遇到这个状态的时候,就不必重新求解了。
这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。

可以归纳为:记忆化搜索=搜索的形式+动态规划的思想


dfs记忆搜索

#include <iostream>#include <fstream>#include <algorithm>#include <string>#include <set>#include <map>#include <queue>#include <utility>#include <stack>#include <list>#include <vector>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>//#include <ctime>#include <ctype.h>using namespace std;#define L long long#define inf 0x3fffffff#define M 1005struct road{int v, w;};int n, dist[M], dp[M];vector<road> g[M]; //保存每个顶点有多少条路径与其它顶点相连bool inq[M];void spfa (int u)    //spfa求home到各个点的最短路{int i, v, w;for (i = 1; i <= n; i++){dist[i] = inf;inq[i] = false;}queue<int> q;q.push (u);dist[u] = 0;inq[u] = true;while (!q.empty()){u = q.front();q.pop();inq[u] = false;for (i = 0; i < g[u].size(); i++){v = g[u][i].v;w = g[u][i].w;if (dist[u] + w < dist[v])    //判断是否可以构造出到v的最短路{dist[v] = dist[u] + w;   //所谓的松弛if (!inq[v]){q.push (v);inq[v] = true;}}}}}int dfs (int u)    //记忆化搜索{if (u == 2)return 1;if (dp[u] > 0)    //核心return dp[u];for (int i = 0; i < g[u].size(); i++){int v = g[u][i].v;if (dist[v] < dist[u])    //满足题意【v相当于B,u相当于A】dp[u] += dfs (v);}return dp[u];}int main(){int m, u, v, w, i;road x;while (scanf ("%d", &n), n){for (i = 1; i <= n; i++)g[i].clear();scanf ("%d", &m);while (m--){scanf ("%d%d%d", &u, &v, &w);x.v = v, x.w = w;g[u].push_back (x);x.v = u;g[v].push_back (x);}spfa (2);    //逆向思维,把终点当成起点memset (dp, 0, sizeof(dp));printf ("%d\n", dfs (1));}return 0;}


 

 

原创粉丝点击