1. 程式人生 > >算法導論 practice4

算法導論 practice4

nds 需要 最優 bound argv practice 循環 width system

1bellman-ford算法

技術分享

每條邊松弛|V|-1次

技術分享

運行結果如下:

(實現的例子)

技術分享

技術分享

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #define maxnum 100
 4 #define maxint 99999
 5  
 6 // 邊,
 7 typedef struct Edge{
 8     int u, v;    // 起點,終點
 9     int weight;  // 邊的權值
10 }Edge;
11  
12 Edge edge[maxnum];     // 保存邊的值
13 int  dist[maxnum];     //
結點到源點最小距離 14 15 int nodenum, edgenum, source; // 結點數,邊數,源點 16 17 // 初始化圖 18 void init() 19 { 20 // 輸入 21 printf("請輸入結點數 邊數 源點:\n"); 22 scanf("%d %d %d",&nodenum, &edgenum, &source); 23 for(int i=1; i<=nodenum; ++i) 24 dist[i] = maxint; 25 dist[source] = 0;
26 27 for(int i=1; i<=edgenum; ++i) 28 { 29 scanf("%d %d %d",&edge[i].u, & edge[i].v,&edge[i].weight); 30 if(edge[i].u == source) //註意這裏設置初始情況 31 dist[edge[i].v] = edge[i].weight; 32 } 33 } 34 35 // 松弛計算 36 void relax(int u, int v, int
weight) 37 { 38 if(dist[v] > dist[u] + weight) 39 dist[v] = dist[u] + weight; 40 } 41 42 bool Bellman_Ford() 43 { 44 for(int i=1; i<=nodenum-1; ++i) 45 for(int j=1; j<=edgenum; ++j) 46 relax(edge[j].u, edge[j].v, edge[j].weight); 47 bool flag = 1; 48 // 判斷是否有負環路 49 for(int i=1; i<=edgenum; ++i) 50 if(dist[edge[i].v] > dist[edge[i].u] + edge[i].weight) 51 { 52 flag = 0; 53 printf("有負環路\n"); 54 break; 55 } 56 printf("沒有負環路\n"); 57 return flag; 58 59 } 60 int main() 61 { 62 init(); 63 if(Bellman_Ford()) 64 for(int i = 1 ;i < nodenum; i++) 65 printf("點s->點%d:%d\n",i,dist[i]); 66 return 0; 67 }

2All-pairs shortest path (choose one from the three algorithms)

技術分享

技術分享

(實現的例子

技術分享

運行結果:

技術分享

 1 #include <cstdlib>
 2 #include <iostream>
 3 #define N 9999
 4 using namespace std;
 5 int l[5][5] = {{0, 3, 8, N, -4}, {N, 0, N, 1, 7}, {N, 4, 0, N, N}, {2, N, -5, 0, N}, {N, N, N, 6, 0}}; 
 6 int w[5][5];
 7 void print()
 8 {
 9      for(int i = 0; i < 5; i++)
10      {
11              for(int j = 0; j < 5; j++)
12                      cout << w[i][j] << " ";
13              cout << endl;
14      }
15 }
16 
17 void ExtendShortestPath()
18 {
19      int t;
20      for(int i = 0; i < 5; i++)
21              for(int j = 0; j < 5; j++)
22              {
23                      t = N;
24                      for(int k = 0; k < 5; k++)//k值代表最多幾條路徑 
25                      {
26                              
27                              if(l[i][j] > l[i][k] + l[k][j] && t > l[i][k] + l[k][j])
28                              {
29                                         w[i][j] = l[i][k] + l[k][j];
30                                         t = w[i][j];
31                              }
32                      }
33              }
34 }
35 
36 int main(int argc, char *argv[])
37 {
38     for(int i = 0; i < 5; i++)
39     {
40             for(int j = 0; j < 5; j++)
41             {
42                             w[i][j] = l[i][j];
43             }
44     }
45     int m;
46     m = 1;
47     while(m < 4)
48     {
49             ExtendShortestPath();
50             m*=2; 
51             print();
52             for(int i = 0; i <5; i++)
53             {
54                     for(int j = 0; j < 5; j++)
55                     {
56                             l[i][j] = w[i][j];
57                     }
58             }
59             cout << endl;
60     }
61     
62     system("PAUSE");
63     return 0;
64 }

38-queen problem (back backing)

技術分享

技術分享

運行結果如下:

技術分享

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3  
 4 #define max 8
 5  
 6  
 7 int queen[max], sum=0; /* max為棋盤最大坐標 */
 8  
 9 void show() /* 輸出所有皇後的坐標 */
10 {
11     int i;
12     for(i = 0; i < max; i++)
13     {
14          printf("(%d,%d) ", i, queen[i]);
15     }
16     printf("\n");
17     sum++;
18 }
19  
20 int check(int n) /* 檢查當前列能否放置皇後 */
21 {
22     int i;
23     for(i = 0; i < n; i++) /* 檢查橫排和對角線上是否可以放置皇後 */
24     {
25         if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == (n - i))
26         {
27             return 1;
28         }
29     }
30     return 0;
31 }
32  
33 void put(int n) /* 回溯嘗試皇後位置,n為橫坐標 */
34 {
35     int i;
36     for(i = 0; i < max; i++)
37     {       
38         queen[n] = i; /* 將皇後擺到當前循環到的位置 */
39         if(!check(n))
40         {           
41             if(n == max - 1)
42             {
43                 show(); /* 如果全部擺好,則輸出所有皇後的坐標 */
44             }         
45             else
46             {
47                 put(n + 1); /* 否則繼續擺放下一個皇後 */
48             }
49         }
50     }
51 }
52  
53 int main()
54 {
55     put(0); /* 從橫坐標為0開始依次嘗試 */
56     printf("\n總方法數:%d", sum);
57     system("pause");
58     return 0;
59 }

40-1 knapsack problem (back tracking)

技術分享

一組數據,有兩種可能:選或不選在樹種用左右字數表示。

使用遞歸,在遍歷完n個,判斷最終的數是否比最佳價值大,如比最佳大,則把值付給besrv

技術分享

上界函數:當前的價值cw+剩余可容納的最大價值<=當前最優解

技術分享

運行結果如下

技術分享

  1 #include <stdio.h>
  2 #include <conio.h>
  3 
  4 int n;//物品數量
  5 double c;//背包容量
  6 double v[100];//各個物品的價值
  7 double w[100];//各個物品的重量
  8 double cw = 0.0;//當前背包重量
  9 double cp = 0.0;//當前背包中物品價值
 10 double bestp = 0.0;//當前最優價值
 11 double perp[100];//單位物品價值排序後
 12 int order[100];//物品編號
 13 int put[100];//設置是否裝入
 14 
 15 //計算上界函數
 16 double bound(int i)
 17 {
 18     double leftw= c-cw;
 19     double b = cp;
 20     while(i<=n&&w[i]<=leftw)
 21     {
 22         leftw-=w[i];
 23         b+=v[i];
 24         i++;
 25     }
 26     if(i<=n)
 27     b+=v[i]/w[i]*leftw;
 28     return b;
 29 }
 30 
 31 //按單位價值排序
 32 void knapsack()
 33 {
 34     int i,j;
 35     int temporder = 0;
 36     double temp = 0.0;
 37     for(i=1;i<=n;i++ )
 38         perp[i]=v[i]/w[i];
 39     for(i=1;i<=n-1;i++)
 40     {
 41         for(j=i+1;j<=n;j++)
 42             if(perp[i]<perp[j])
 43             {
 44                 temp = perp[i];
 45                 perp[i]=perp[i];
 46                 perp[j]=temp;
 47                 temporder=order[i];
 48                 order[i]=order[j];
 49                 order[j]=temporder;
 50                 temp = v[i];
 51                 v[i]=v[j];
 52                 v[j]=temp;
 53                 temp=w[i];
 54                 w[i]=w[j];
 55                 w[j]=temp;
 56             }
 57     }
 58 }
 59 
 60 //回溯函數
 61 void backtrack(int i)
 62 {
 63     double bound(int i);
 64     if(i>n)
 65     {
 66         bestp = cp;
 67         return;
 68     }
 69     if(cw+w[i]<=c)
 70     {
 71         cw+=w[i];
 72         cp+=v[i];
 73         put[i]=1;
 74         backtrack(i+1);
 75         cw-=w[i];
 76         cp-=v[i];
 77     }
 78     if(bound(i+1)>bestp)//符合條件搜索右子數
 79         backtrack(i+1);
 80 }
 81 
 82 int main()
 83 {
 84     int i;
 85     printf("請輸入物品的數量和容量:");
 86     scanf("%d %lf",&n,&c);
 87     printf("請輸入物品的重量和價值:");
 88     for(i=1;i<=n;i++)
 89     {
 90         printf("第%d個物品的重量和價值:",i);
 91     scanf("%lf",&w[i],&v[i]);
 92     printf("第%d個物品的價值:",i);
 93     scanf("%lf",&v[i]);
 94     order[i]=i;
 95     }
 96     knapsack();
 97     backtrack(1);
 98     printf("最有價值為:%lf\n",bestp);
 99     printf("需要裝入的物品編號是:");
100     for(i=1;i<=n;i++)
101     {
102         if(put[i]==1)
103         printf("%d ",order[i]);
104     }
105     return 0;
106 }

算法導論 practice4