http://acm.hdu.edu.cn/showproblem.php?pid=1142
题意:他的办公室用1表示,家用2 表示,从1到2,中间可能会经过其它节点,而该节点可走的原则是:假设他此时在A处,B与其相邻,只有当B到2 路线中存在一条比A到2 的任意一条路径都短的路径,才能走B。问这样的路线有多少种?
分析:记忆化搜索不太会,这题难度就在这里。有挑战好玩。下面是大神的分析。欣赏下。
题目大意:寻找一共有多少条符合题意的路。能够从点A走到点B的要求是:点A到终点的最短路 > 点B到终点的最短路。 也就是说:从终点出发,求每一个点的最短路,然后那些最短路的值记录起来,作为能否通过的判断条件。最后用记忆化搜索来搜索出一共多少条符合要求的路。普通的dfs是超时的,bfs是超内存的。
http://gzhu-101majia.iteye.com/blog/1151203
分析2:
做这题真可谓是一波三折, 足足WA了有30+次。
1. 题目意思懂得错误。题目中的一段话没懂得好:
He considers taking a path A to B to be progress if there exists a route B to his home that is shorter than any possible route A.
这句话的意思是说,对于两点A,B, 若是点B达到家里的最短路间隔小于点A达到家里的最短路间隔,那么点A就可以达到点B。
而我把这题懂得成了求有办公室到家里有几许条不合的最短路。
2. 解决了上述错误之后,接下来可以求出每一点达到点2(家里)的最短路,然后按照所求的各点最短路,求出有几许条到家里的路径。
若是直接搜刮是会超时的,所以要用记忆化搜刮。
3. 因为本身的粗心, 因为我的法度中有两个数组名为d和dp, 在写记忆话搜刮时把这两个数组混合了,成果又WA了十多次而找不到原因。
http://www.cesclub.com/bw/jishuzhongxin/bianchengyuyan/2012/1017/44129.html
分析3: 设定一个DP数组,DP[i] 表示第i点到点2有多少种符合条件的走法。然后用递归的方法从1点求出到2点的符合条件的走法。具体思想看代码。
http://blog.csdn.net/xiezefan/article/details/7910991

// I'm lanjiangzhou //C #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <math.h> #include <time.h> //C++ #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <cctype> #include <stack> #include <string> #include <list> #include <queue> #include <map> #include <vector> #include <deque> #include <set> using namespace std; //*************************OUTPUT************************* #ifdef WIN32 #define INT64 "%I64d" #define UINT64 "%I64u" #else #define INT64 "%lld" #define UINT64 "%llu" #endif //**************************CONSTANT*********************** #define INF 0x3f3f3f3f // aply for the memory of the stack //#pragma comment (linker, "/STACK:1024000000,1024000000") //end #define maxn 1010 int n,m; int edge[maxn][maxn]; int S[maxn]; int dis[maxn]; int path[maxn]; int dp[maxn]; void dijkstra(int v0){ //初始化 for(int i=0;i<n;i++){ dis[i]=edge[v0][i]; S[i]=0; if(i!=v0&&dis[i]<INF) path[i]=v0; else path[i]=-1; } S[v0]=1; dis[v0]=0; //从顶点v0确定n-1条最短路径 for(int i=0;i<n-1;i++){ int min=INF, u=v0; //选择当前集合T中具有最短路径的顶点u for(int j=0;j<n;j++){ if(!S[j]&&dis[j]<min){ u=j; min=dis[j]; } } S[u]=1; //修改T集合中顶点的dist和path数组元素值 for(int k=0;k<n;k++){ if(!S[k]&&edge[u][k]<INF&&dis[u]+edge[u][k]<dis[k]){ dis[k]=dis[u]+edge[u][k]; path[k]=u; } } } } //记忆化深搜 int dfs(int v){ if(dp[v]!=-1){//该点已经走过,返回:过该点有多少条路 return dp[v]; } if(v==1 ) return 1;//找到终点,返回1(1条路) int sum=0; for(int i=0;i<n;i++){ //有路相通而且要去的i点到终点站的距离要比v到终点站的距离小 if(edge[v][i]!=INF&&dis[v]>dis[i]){ int t=dfs(i); sum+=t; } } dp[v]=sum; return sum; //返回:该点一共可以有多少条路 } int main(){ int u,v,w; while(scanf("%d",&n)!=EOF){ if(n==0 ) break; scanf("%d",&m); //初始化 for(int i=0;i<n;i++){ dp[i]=-1; for(int j=0;j<n;j++){ if(i==j) edge[i][j]=0; else edge[i][j]=INF; } //if(i==j) edge[i][j]=0; } for(int i=0;i<m;i++){ scanf("%d%d%d",&u,&v,&w); u--; v--; edge[u][v]=w; edge[v][u]=w; } //求出各点到终点站的最短距离(终点作为起点) dijkstra(1); printf("%d\n",dfs(0)); } return 0; }