求出从1到n的最短路径 并且输出经过的点
第一行一个整数n,接下来输入一个n*n的矩阵,第i行第j列的数表示i到j有一条长度为此数的路径,若为0则不存在此路径,并且数据保证当i>=j输入的数为0
输出第一行minlong=路径长度,第二行输出经过的点的编号
样例输入
10
0 2 5 1 0 0 0 0 0 0
0 0 0 0 12 14 0 0 0 0
0 0 0 0 6 10 4 0 0 0
0 0 0 0 13 12 11 0 0 0
0 0 0 0 0 0 0 3 9 0
0 0 0 0 0 0 0 6 5 0
0 0 0 0 0 0 0 0 10 0
0 0 0 0 0 0 0 0 0 5
0 0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 0 0
样例输出
minlong=19
1 3 5 8 10
n<=15 题目保证图的连通性
之前好像学过一点DP,但发现仍是一脸懵逼……所以现在重新温故一遍(对不起学长Orz)。这是一道很基础的入门DP(然而现在我才会),所以说论预习的重要性,否则就是白费了学长的心血
解析:
- 首先邻接矩阵记录路径长度不多说
- 然后我们从终点推向起点
- DP条件:
- 得有路走(mp[i][j] > 0)
- 从后往前,走过的路得是更新过的
- 当前的方向上挑最短路走
代码如下:
#include<stdio.h> #include<algorithm> using namespace std; const int inf = 0x7ffffff; int mp[16][16],f[16],rout[2002]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) { f[i]=inf; for(int j=1;j<=n;++j){ scanf("%d",&mp[i][j]); } } f[n]=0; for(int i=n-1;i>=1;--i) { for(int j=i+1;j<=n;++j) { if(mp[i][j]>0 && f[j]!=inf && (mp[i][j]+f[j]<f[i])) { f[i]=f[j]+mp[i][j]; rout[i]=j; } } } printf("minlong=%d ",f[1]); int x=1; while(x!=0) { printf("%d ",x); x=rout[x]; } return 0; }