标签:
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include<stdio.h> #include<stdlib.h> #define max 11000000000 inta[1000][1000]; intd[1000]; //d表示某特定边距离 intp[1000]; //p表示永久边距离 inti,j,k; intm; //m代表边数 intn; //n代表点数 intmain() { scanf ( "%d%d" ,&n,&m); intmin1; intx,y,z; for (i=1;i<=m;i++) { scanf ( "%d%d%d" ,&x,&y,&z); a[x][y]=z; a[y][x]=z; } for (i=1;i<=n;i++) d[i]=max1; d[1]=0; for (i=1;i<=n;i++) { min1=max1; for (j=1;j<=n;j++) if (!p[j]&&d[j]<min1) { min1=d[j]; k=j; } p[k]=j; for (j=1;j<=n;j++) if (a[k][j]!=0&&!p[j]&&d[j]>d[k]+a[k][j]) d[j]=d[k]+a[k][j]; } for (i=1;i<n;i++) printf ( "%d->" ,p[i]); printf ( "%d\n" ,p[n]); return0; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/* 测试数据 教科书 P189 G6 的邻接矩阵 其中 数字 1000000 代表无穷大 6 1000000 1000000 10 100000 30 100 1000000 1000000 5 1000000 1000000 1000000 1000000 1000000 1000000 50 1000000 1000000 1000000 1000000 1000000 1000000 1000000 10 1000000 1000000 1000000 20 1000000 60 1000000 1000000 1000000 1000000 1000000 1000000 结果: D[0] D[1] D[2] D[3] D[4] D[5] 0 1000000 10 50 30 60 */ #include <iostream> #include <cstdio> #define MAX 1000000 using namespace std; int arcs[10][10]; //邻接矩阵 int D[10]; //保存最短路径长度 int p[10][10]; //路径 int final[10]; //若final[i] = 1则说明 顶点vi已在集合S中 int n = 0; //顶点个数 int v0 = 0; //源点 int v,w; void ShortestPath_DIJ() { for (v = 0; v < n; v++) //循环 初始化 { final[v] = 0; D[v] = arcs[v0][v]; for (w = 0; w < n; w++) p[v][w] = 0; //设空路径 if (D[v] < MAX) {p[v][v0] = 1; p[v][v] = 1;} } D[v0] = 0; final[v0]=0; //初始化 v0顶点属于集合S //开始主循环 每次求得v0到某个顶点v的最短路径 并加v到集合S中 for ( int i = 1; i < n; i++) { int min = MAX; for (w = 0; w < n; w++) { //我认为的核心过程--选点 if (!final[w]) //如果w顶点在V-S中 { //这个过程最终选出的点 应该是选出当前V-S中与S有关联边 //且权值最小的顶点 书上描述为 当前离V0最近的点 if (D[w] < min) {v = w; min = D[w];} } } final[v] = 1; //选出该点后加入到合集S中 for (w = 0; w < n; w++) //更新当前最短路径和距离 { /*在此循环中 v为当前刚选入集合S中的点 则以点V为中间点 考察 d0v+dvw 是否小于 D[w] 如果小于 则更新 比如加进点 3 则若要考察 D[5] 是否要更新 就 判断 d(v0-v3) + d(v3-v5) 的和是否小于D[5] */ if (!final[w] && (min+arcs[v][w]<D[w])) { D[w] = min + arcs[v][w]; // p[w] = p[v]; p[w][w] = 1; //p[w] = p[v] + [w] } } } } int main() { cin >> n; for ( int i = 0; i < n; i++) { for ( int j = 0; j < n; j++) { cin >> arcs[i][j]; } } ShortestPath_DIJ(); for ( int i = 0; i < n; i++) printf ( "D[%d] = %d\n" ,i,D[i]); return 0; } |
标签:
原文地址:http://blog.csdn.net/lieacui/article/details/51750682