找回密码
 欢迎注册
楼主: kon3155

[分享] 经典算法普及——基础篇

[复制链接]
 楼主| 发表于 2009-2-25 12:28:54 | 显示全部楼层
接上贴:

1。根据算法1计算24点的代码

  1. #include <iostream>
  2. #include <string>
  3. #include <cmath>

  4. using namespace std;

  5. const double PRECISION = 1E-6;
  6. const int COUNT_OF_NUMBER  = 4;
  7. const int NUMBER_TO_CAL = 24;

  8. double number[COUNT_OF_NUMBER];
  9. string expression[COUNT_OF_NUMBER];

  10. bool Search(int n)
  11. {
  12.     if (n == 1) {
  13.         if ( fabs(number[0] - NUMBER_TO_CAL) < PRECISION ) {
  14.             cout << expression[0] << endl;
  15.             return true;
  16.         } else {
  17.             return false;
  18.         }
  19.     }

  20.     for (int i = 0; i < n; i++) {
  21.         for (int j = i + 1; j < n; j++) {
  22.             double a, b;
  23.             string expa, expb;

  24.             a = number[i];
  25.             b = number[j];
  26.             number[j] = number[n - 1];

  27.             expa = expression[i];
  28.             expb = expression[j];
  29.             expression[j] = expression[n - 1];

  30.             expression[i] = '(' + expa + '+' + expb + ')';
  31.             number[i] = a + b;
  32.             if ( Search(n - 1) ) return true;
  33.             
  34.             expression[i] = '(' + expa + '-' + expb + ')';
  35.             number[i] = a - b;
  36.             if ( Search(n - 1) ) return true;
  37.             
  38.             expression[i] = '(' + expb + '-' + expa + ')';
  39.             number[i] = b - a;
  40.             if ( Search(n - 1) ) return true;
  41.                         

  42.             expression[i] = '(' + expa + '*' + expb + ')';
  43.             number[i] = a * b;
  44.             if ( Search(n - 1) ) return true;

  45.             if (b != 0) {
  46.                 expression[i] = '(' + expa + '/' + expb + ')';
  47.                 number[i] = a / b;
  48.                 if ( Search(n - 1) ) return true;
  49.             }
  50.             if (a != 0) {
  51.                 expression[i] = '(' + expb + '/' + expa + ')';
  52.                 number[i] = b / a;
  53.                 if ( Search(n - 1) ) return true;
  54.             }

  55.             number[i] = a;
  56.             number[j] = b;
  57.             expression[i] = expa;
  58.             expression[j] = expb;
  59.         }
  60.     }
  61.     return false;
  62. }

  63. void main()
  64. {
  65.     for (int i = 0; i < COUNT_OF_NUMBER; i++) {
  66.         char buffer[20];
  67.         int  x;
  68.         cin >> x;
  69.         number[i] = x;
  70.         itoa(x, buffer, 10);
  71.         expression[i] = buffer;
  72.     }

  73.     if ( Search(COUNT_OF_NUMBER) ) {
  74.         cout << "Success." << endl;
  75.     } else {
  76.         cout << "Fail." << endl;
  77.     }        
  78. }
复制代码
2。根据算法2计算解决题目的程序代码:


  1. #include <fstream>
  2. #include <algorithm>
  3. #include <string>
  4. #include <sstream>
  5. #include <list>
  6. #include <cmath>
  7. #include <climits>
  8. #include <bitset>
  9. using namespace std;

  10. const char* INPUT_FILE  = "game.in";
  11. const char* OUTPUT_FILE = "game.out";
  12. const int NUMBER_COUNT  = 6;
  13. const int STATE_COUNT   = (1 << NUMBER_COUNT);
  14. const int MAX_NUMBER    = 100;
  15. const int MAX_EXPECTION = 1000;
  16. const int MAX_VALUE             = MAX_EXPECTION * MAX_NUMBER;

  17. struct Node {
  18.         int value;
  19.         int left, right;        
  20.         int leftvalue, rightvalue;
  21.         char opr;
  22. };

  23. typedef list<Node> NodeList;

  24. struct State {
  25.         bitset<MAX_VALUE+10> exist;
  26.         NodeList nodelist;
  27. };

  28. int number[NUMBER_COUNT], expection;
  29. State state[STATE_COUNT];

  30. void ReadData()
  31. {
  32.         ifstream fin(INPUT_FILE);
  33.         
  34.         for (int i = 0; i < NUMBER_COUNT; i++) {
  35.                 fin >> number[i];
  36.         }
  37.         fin >> expection;
  38. }

  39. void Init()
  40. {
  41.         Node node ;
  42.         for (int i = 0; i < NUMBER_COUNT; i++) {
  43.                 node.value              = number[i];
  44.                 node.left = node.right = -1;
  45.                 state[(1 << i)].nodelist.push_back(node);
  46.                 state[(1 << i)].exist[node.value] = true;
  47.         }
  48. }

  49. void Merge(int a, int b, int x)
  50. {      
  51.         Node node;      
  52.         NodeList::const_iterator i, j;

  53.         for (i = state[a].nodelist.begin(); i != state[a].nodelist.end();
  54. i++) {
  55.                 for (j = state[b].nodelist.begin(); j != state[b].nodelist.en

  56. d(); j++)
  57. {                                      
  58.                         node.value = (*i).value + (*j).value;
  59.                         node.left  = a;
  60.                         node.right = b;                 
  61.                         node.leftvalue  = (*i).value;
  62.                         node.rightvalue = (*j).value;
  63.                         node.opr   = '+';
  64.                         if ( (node.value <= MAX_VALUE) && (!state[x].exist[no

  65. de.value]) ) {
  66.                                 state[x].nodelist.push_back(node);
  67.                                 state[x].exist[node.value] = true;
  68.                         }

  69.                         /////////////////////////////////////////////////////

  70.                         double tmp = double((*i).value) * double((*j).value);

  71.                         if (tmp < INT_MAX) {
  72.                                 node.value = (*i).value * (*j).value;
  73.                                 node.left  = a;
  74.                                 node.right = b;
  75.                                 node.leftvalue  = (*i).value;
  76.                                 node.rightvalue = (*j).value;
  77.                                 node.opr   = '*';
  78.                                 if ( (node.value <= MAX_VALUE) && (!state[x].

  79. exist[node.value]) )
  80. {
  81.                                         state[x].nodelist.push_back(node);
  82.                                         state[x].exist[node.value] = true;
  83.                                 }
  84.                         }

  85.                         /////////////////////////////////////////////////////

  86.                         if ((*i).value >= (*j).value) {
  87.                                 node.value = (*i).value - (*j).value;
  88.                                 node.left  = a;
  89.                                 node.right = b;
  90.                                 node.leftvalue  = (*i).value;
  91.                                 node.rightvalue = (*j).value;
  92.                                 node.opr   = '-';
  93.                         } else {
  94.                                 node.value = (*j).value - (*i).value;
  95.                                 node.left  = b;
  96.                                 node.right = a;
  97.                                 node.leftvalue  = (*j).value;
  98.                                 node.rightvalue = (*i).value;
  99.                                 node.opr   = '-';
  100.                         }
  101.                                                 
  102.                         if ( (node.value <= MAX_VALUE) && (!state[x].exist[no

  103. de.value]) ) {
  104.                                 state[x].nodelist.push_back(node);
  105.                                 state[x].exist[node.value] = true;
  106.                         }

  107.                         /////////////////////////////////////////////////////


  108.                         if ( ((*j).value != 0) && ((*i).value >= (*j).value) &
  109. &
  110.                                         ((*i).value % (*j).value == 0) )
  111.                         {
  112.                                 node.value = (*i).value / (*j).value;
  113.                                 node.left  = a;
  114.                                 node.right = b;         
  115.                                 node.leftvalue  = (*i).value;
  116.                                 node.rightvalue = (*j).value;
  117.                                 node.opr   = '/';
  118.                         } else if ( ((*i).value != 0) && ((*j).value >= (*i).

  119. value) &&
  120.                                         ((*j).value % (*i).value == 0) )
  121.                         {
  122.                                 node.value = (*j).value / (*i).value;
  123.                                 node.left  = b;
  124.                                 node.right = a;
  125.                                 node.leftvalue  = (*j).value;
  126.                                 node.rightvalue = (*i).value;
  127.                                 node.opr   = '/';
  128.                         }
  129.                                                 
  130.                         if ( (node.value <= MAX_VALUE) && (!state[x].exist[no

  131. de.value]) )
  132. {                              
  133.                                 state[x].nodelist.push_back(node);
  134.                                 state[x].exist[node.value] = true;
  135.                         }                       
  136.                         /////////////////////////////////////////////////////

  137.                 }
  138.         }
  139. }

  140. void Solve()
  141. {
  142.         Init();
  143.         
  144.         for (int x = 2; x < STATE_COUNT; x++) {
  145.                 for (int i = 1; i < x; i++) {                  
  146.                         if ( (x & i) == i ) {
  147.                                 int j = x - i;
  148.                                 if (i <= j) {
  149.                                         Merge(i, j, x);         
  150.                                 }
  151.                         }
  152.                 }
  153.         }
  154. }

  155. void PrintExpression(ostream& out, Node node)
  156. {
  157.         if (node.left == -1) {
  158.                 out << node.value;
  159.         } else {
  160.                 NodeList::const_iterator iter;
  161.                
  162.                 out << "(";

  163.                 for (iter = state[node.left].nodelist.begin();
  164.                                 iter != state[node.left].nodelist.end();
  165.                                 iter++)
  166.                 {
  167.                         if ((*iter).value == node.leftvalue) {
  168.                                 PrintExpression(out, *iter);
  169.                                 break;
  170.                         }
  171.                 }

  172.                 out << node.opr;

  173.                 for (iter = state[node.right].nodelist.begin();
  174.                                 iter != state[node.right].nodelist.end();
  175.                                 iter++)
  176.                 {
  177.                         if ((*iter).value == node.rightvalue) {
  178.                                 PrintExpression(out, *iter);
  179.                                 break;
  180.                         }
  181.                 }

  182.                 out << ")";
  183.         }               
  184. }

  185. void Output()
  186. {
  187.         ofstream fout(OUTPUT_FILE);

  188.         int bestValue = -INT_MAX;      
  189.         NodeList::const_iterator iter, bestIter;

  190.         NodeList& nodelist = state[STATE_COUNT-1].nodelist;

  191.         for (iter = nodelist.begin(); iter != nodelist.end(); iter++)
  192.         {      
  193.                 if ( ((*iter).value <= expection) && (bestValue < (*iter).val

  194. ue) ) {
  195.                         bestValue = (*iter).value;
  196.                         bestIter  = iter;
  197.                 }
  198.         }      
  199.         fout << bestValue << endl;
  200.         PrintExpression(fout, *bestIter );
  201.         fout << endl;
  202. }

  203. int main()
  204. {
  205.         ReadData();
  206.         Solve();
  207.         Output();
  208.         return 0;
  209. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:38:12 | 显示全部楼层
无向图的生成树就是从图的边集中选择一些边,使得这些边构成一个连通无环图,也就是树。如果给每一条边加一个权,所有生成树中权和最小的生成树称为最小生成树。
【Prim算法思想】
任意时刻的中间结果都是一棵树,每次花费最小的代价,用一条边把不在树中的结点加进来。
【最小生成树算法实例】
    现有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权代表公路造价。在分析了这张图后发现,任一对城市都是连通的。现在要求用公路把所有城市联系起来,如何设计可使得工程的总造价最少?
【输入】 第一行两个数v(v<=200),e,分别代表城市数和边数 以下e行,每行为两个顶点和它们之间的边权w(w<1000)。
【输出】 v-1行,每行为两个城市的序号,表明这两个城市间建一条公路,再加该公路的造价。
 【输入样例】
6 10
1 2 10
1 5 19
1 6 21
2 3 5
2 4 6
2 6 11
3 4 6
4 5 18
4 6 14
5 6 33
 
【输出样例】
1 2 10
2 3 5
2 4 6
2 6 11
4 5 18
 
原  图

最小生成树
  1. program prim_example;
  2. Const
  3.    vmax=200
  4. var
  5.    w:array[1..vmax,1..vmax]of integer;
  6.    i,j,k,v,e:integer;
  7. procedure prim(v0:integer); {v0是开始结点}
  8.   var
  9.     flag:array[1..vmax] of boolean;
  10.     min,prevk,nextk:integer;
  11.   begin
  12.     fillchar(flag,sizeof(flag),false);
  13.     flag[v0]:=true; {先选出v0}
  14.     for i:=1 to v-1 do {一共寻找v-1条边}
  15.       begin
  16.         min:=maxint;
  17.           for k:=1 to v do
  18.             if flag[k] then {找已在集合中的顶点}
  19.               for j:=1 to v do {求满足条件的边的最小值}
  20.                  if (not(flag[j])) and (w[k,j]<min) and (w[k,j]<>0)
  21.                     then begin
  22.                           min:=w[k,j]; {记下最小值}
  23.                           nextk:=j;
  24.                           prevk:=k;
  25.                          end;
  26.                  if min<>maxint
  27.                     then begin
  28.                           flag[nextk]:=true; {最小值对应顶点进入集合}
  29.                           writeln(prevk,' ',nextk,‘ ',min);
  30.                          end;
  31.              end;{for}
  32.    end;{prim}
  33. begin
  34.   assign(input,'prim.in');
  35.   reset(input);
  36.   assign(output,'prim.out');
  37.   rewrite(output);
  38.   fillchar(w,sizeof(w),0);
  39.   readln(v,e);
  40.   for k:=1 to e do
  41.     begin
  42.       read(i,j);
  43.       readln(w[i,j]);
  44.       w[j,i]:=w[i,j];
  45.     end;
  46.   prim(1);
  47.   close(input);
  48.   close(output);
  49. end.
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:40:11 | 显示全部楼层
设图G=(V,E)是一个有向图,它的每一条边(U,V)都有一个非负权W(U,V),在G中指定一个结点V0,要求从V0到G的每一个结点Vj的最短路径找出来(或指出不存在)。
    由于源结点V0是给定的,所谓称为单源最短路径。
【Dijkstra算法思想】
   把所有结点分为两组。
   第一组:包含已确定最短路径的结点。
   第二组:包含尚未确定最短路径的结点。
   按最短路径长度递增的顺序把第二组的结点加到第一组中去,直到V0可达的所有结点都包含于第一组中。在这个过程中,总保持从V0到第一组各结点的最短路径长度都不大于从V0到第二组任何结点的路径长度。
【单源最短路径算法实例】
    现有一张县城的城镇地图,图中的顶点为城镇,无向边代表两个城镇间的连通关系,边上的权为公路造价,县城所在的城镇为v0。由于该县经济比较落后,因此公路建设只能从县城开始规划。规划的要求是所有可到达县城的城镇必须建设一条通往县城的汽车线路,该线路的工程总造价必须最少。
【输入】 第一行一个整数v,代表城镇数,县城编号为1。 第二行是一个整数e,表示有向边数。 以下e行,每行为两个城镇编号和它们之间的公路造价。
【输出】 v-1行,每行为两个城市的序号,表明这两个城市间建一条公路。
 【输入样例】
6
10
1 2 10
1 5 19
1 6 21
2 3 5
2 4 6
2 6 11
3 4 6
4 5 18
4 6 14
5 6 33
 
【输出样例】
1 2
2 3
2 4
1 5
1 6            

原    图

从第1点出发的最短路径

【参考程序】
  1. program dijkstra_example;
  2. const
  3.   vmax=100;
  4. type
  5.   path=record                  {此记录类型用于记录每一个结点与v0的距离和其父结点}
  6.         length:integer;
  7.         pre:0..vmax;
  8.        end;
  9. var
  10.   w:array[1..vmax,1..vmax] of integer;
  11.   dist:array[1..vmax] of path;
  12.   v,e,u,i,j,x,y:integer;
  13. procedure init;
  14.   begin
  15.     assign(input,'dijkstra.in');
  16.     reset(input);
  17.     assign(output,'dijkstra.out');
  18.     rewrite(output);
  19.     readln(v);
  20.     readln(e);
  21.     for i:=1 to v do
  22.       for j:=1 to v do
  23.         if i<>j
  24.           then w[i,j]:=30000
  25.    {30000只是一个较大的数的意思,实际应用于应该根据题目中给出的取值范围赋予一个充分大的数}
  26.           else w[i,j]:=0;
  27.     for i:=1 to e do
  28.       begin
  29.         read(x,y);
  30.         readln(w[x,y]);
  31.         w[y,x]:=w[x,y];
  32.       end;
  33.   end;
  34. procedure dijkstra(v0:integer);
  35.   var
  36.     min:integer;
  37.   begin
  38.     w[v0,v0]:=1;                {v0首先进入第一组}
  39.     for i:=1 to v do
  40.      begin
  41.        dist[i].length:=w[v0,i];   {计算每个结点的距离值}
  42.        if dist[i].length<>30000
  43.          then dist[i].pre:=v0     {如和v0直接有路,则置前驱结点为v0}
  44.          else dist[i].pre:=0;
  45.       end;
  46.   repeat
  47.     min:=30000;
  48.     u:=0;
  49.     for i:=1 to v do             {找最短距离}
  50.       if (w[i,i]=0) and (dist[i].length<min)
  51.          then begin
  52.                u:=i;
  53.                min:=dist[i].length;
  54.              end;
  55.     if u<>0
  56.       then begin
  57.             w[u,u]:=1;
  58.             for i:=1 to v do         {重新计算其他结点的距离值}
  59.               if (w[i,i]=0) and (dist[i].length>dist[u].length+w[u,i])
  60.                 then begin
  61.                       dist[i].length:=dist[u].length+w[u,i];
  62.                       dist[i].pre:=u;
  63.                      end;
  64.             end;
  65.   until u=0;
  66. end;
  67. begin
  68.   init;
  69.   v0:=1;
  70.   dijkstra(v0);
  71.   for i:=1 to v do
  72.     begin
  73.       if (i<>v0) and (dist[i].length<>30000)
  74.          then write(dist[i].pre,' ',i);
  75.     end;
  76.   close(input);
  77.   close(output);
  78. end.

复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:41:34 | 显示全部楼层
设图G=(V,E)是一个有向图,对于每对结点(U,V),找出从U到V的最短路径。
【Floyd算法思想】
    利用一个三重循环产生一个存储每个结点最短距离的矩阵.
【Floyd算法实例】
    现有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权代表城市之间的距离。求每个城市的最短距离
【输入】 第一行两个数v,e,分别代表城市数和边数 以下e行,每行为两个顶点和它们之间的边权。
【输出】 所有可能连接的城市的最短距离。
 【输入样例】
6 10
1 2 10
1 5 19
1 6 21
2 3 5
2 4 6
2 6 11
3 4 6
4 5 18
4 6 14
5 6 33

【输出样例】
1 2 10
1 3 15
1 4 16
1 5 19
1 6 21
2 3 5
2 4 6
2 5 24
2 6 11
3 4 6
3 5 24
3 6 16
4 5 18
4 6 14
5 6 32   


【参考程序】
  1. program floyd_example;
  2. const
  3.   maxn=10;
  4. var
  5.   n,s,t,i,j:integer;
  6.   dist:array[1..maxn,1..maxn] of real;
  7.   prev:array[1..maxn,1..maxn] of 0..maxn;
  8. procedure init;
  9.   var
  10.     m,i,u,v:integer;
  11.   begin
  12.     assign(input,'floyd.in');
  13.     reset(input);
  14.     assign(output,'floyd.out');
  15.     rewrite(output);
  16.     readln(n,m);
  17.     fillchar(prev,sizeof(prev),0);
  18.     for u:=1 to n do
  19.      for v:=1 to n do
  20.        dist[u,v]:=1e10;
  21.     for i:=1 to m do
  22.       begin
  23.         readln(u,v,dist[u,v]);
  24.         dist[v,u]:=dist[u,v];
  25.         prev[u,v]:=u;
  26.         prev[v,u]:=v;
  27.      end;
  28.   end;{init}
  29. procedure floyd;
  30.   var
  31.     i,j,k:integer;
  32.   begin
  33.     for k:=1 to n do
  34.       for i:=1 to n do
  35.          for j:=1 to n do
  36.            if (dist[i,k]+dist[k,j]<dist[i,j])
  37.               then  begin
  38.                  dist[i,j]:=dist[i,k]+dist[k,j];
  39.                  prev[i,j]:=prev[k,j];
  40.                 end;
  41.   end;{floyd}
  42. procedure print(i,j:integer);
  43.   begin
  44.     if i=j
  45.       then write(i)
  46.       else if prev[i,j]=0
  47.              then write('No Solution!')
  48.              else begin
  49.                   print(i,prev[i,j]);
  50.                   write('->',j);
  51.                   end;
  52.   end;{print}
  53. begin
  54.   init;
  55.   floyd;
  56.   for i:=1 to n do
  57.     for j:=i+1 to n do
  58.       begin
  59.         write(i,' ',j,' ');
  60.         write(dist[i,j]:0:0,' ');
  61.         print(i,j);
  62.         writeln;
  63.       end;
  64.   close(input);
  65.   close(output);
  66. end.
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:43:27 | 显示全部楼层
求有向图的所有环,此问题包括了求最大环或者最小环。
【输入】
第一行两个数v,e,分别代表图的顶点数和边数,以下e行,每行为有连接的两个顶点和权。
【输出】
顶点编号和环的长度以及包含该顶点的环的路径。
 【输入样例】 huan.in
5 7
1 2 2
2 1 1
2 5 4
3 2 5
3 4 7
4 1 3
5 4 6
                                                                  
【输出样例】 huan.out
1 3 1->2
2 3 2->1
4 15 4->1->2->5
5 15 5->4->1->2

【参考程序】
  1. program huan;
  2. const
  3.   maxn=90;
  4. var
  5.   n,s,t,i,j:integer;
  6.   dist:array[1..maxn,1..maxn] of real;
  7.   prev:array[1..maxn,1..maxn] of 0..maxn;
  8. procedure init;
  9.   var
  10.     m,i,u,v:integer;
  11.   begin
  12.     assign(input,'huan.in');
  13.     reset(input);
  14.     assign(output,'huan.out');
  15.     rewrite(output);
  16.     readln(n,m);
  17.     fillchar(prev,sizeof(prev),0);
  18.     for u:=1 to n do
  19.       for v:=1 to n do
  20.         dist[u,v]:=1e10;
  21.      for i:=1 to m do
  22.       begin
  23.         readln(u,v,dist[u,v]);
  24.         prev[u,v]:=u;
  25.       end;  
  26.   end;
  27. procedure floyd;
  28. var
  29.    i,j,k:integer;
  30. begin
  31.    for k:=1 to n do
  32.      for i:=1 to n do
  33.        for j:=1 to n do
  34.          if (dist[i,k]+dist[k,j]<dist[i,j])
  35.              then  begin
  36.                dist[i,j]:=dist[i,k]+dist[k,j];
  37.                prev[i,j]:=prev[k,j];
  38.               end;
  39.   end;{floyd}
  40. procedure print(i,j:integer);
  41.   begin
  42.    if i=j
  43.      then write(i)
  44.      else if prev[i,j]=0
  45.             then write('No Circle!')
  46.             else begin
  47.                 print(i,prev[i,j]);
  48.                 write('->',j);
  49.                 end;
  50.   end;{print}
  51. begin
  52.   init;
  53.   floyd;
  54.   for i:=1 to n do
  55.      begin
  56.         if dist[i,i]<>1e10
  57.           then
  58.             begin
  59.               write(i,' ');
  60.               write(dist[i,i]:0:0,' ');
  61.               print(i,prev[i,i]);
  62.               writeln;
  63.             end;
  64.       end;
  65.   close(input);
  66.   close(output);
  67. end.
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:44:34 | 显示全部楼层
Dijkstra算法中要求边的权非负,如果遇到负权,则可以采用Bellman-Ford算法。
【Bellman-Ford算法思想】
   
【Bellman-Ford算法实例】
 【输入样例】
6
10
1 2 -10
1 5 19
1 6 21
2 3 5
2 4 6
2 6 11
3 4 -6
4 5 18
4 6 14
5 6 -33
1 4 

【输出样例】
length=-11
1->2->3->4   

【参考程序】

  1. program bellman_ford;
  2. const
  3.   maxn=30;
  4. var
  5.   n,s,t:integer;
  6.   dist:array[1..maxn] of real;
  7.   w:array[1..maxn,1..maxn] of real;
  8.   pre:array[1..maxn] of integer;
  9.   vis:array[1..maxn] of boolean;
  10. procedure init;
  11.   var
  12.    m,i,u,v:integer;
  13.   begin
  14.    assign(input,'bellford.in');
  15.    reset(input);
  16.    assign(output,'bellford.out');
  17.    rewrite(output);
  18.    readln(n,m);
  19.    for u:=1 to n do
  20.     for v:=1 to n do
  21.       w[u,v]:=1e38;
  22.    for i:=1 to m do
  23.      readln(u,v,w[u,v]);
  24.    readln(s,t);                    {求结点s和结点t的最短距离和路径}
  25.   end;{init}
  26. procedure bellford;
  27.   var
  28.     i,j:integer;
  29.     change:boolean;
  30.   begin
  31.     for i:=1 to n do
  32.       dist[i]:=1e38;
  33.     dist[s]:=0;
  34.   repeat
  35.     change:=false;              {记录递推序列是否改变}
  36.      for i:=1 to n do
  37.        for j:=1 to n do
  38.          if dist[i]+w[i,j]<dist[j]
  39.            then begin
  40.                   dist[j]:=dist[i]+w[i,j];
  41.                   pre[j]:=i;
  42.                   change:=true;
  43.                 end;
  44.    until not change;
  45.   end;{bellford}
  46. procedure out(s,t:integer);
  47.   var
  48.     k,length,i:integer;
  49.     path:array[1..maxn] of integer;
  50.   begin
  51.     if (dist[t])>1e38
  52.       then writeln('No solutin.')
  53.       else begin
  54.              length:=0;
  55.              k:=t;
  56.              while (k<>s) do
  57.                begin
  58.                  inc(length);
  59.                  path[length]:=k;
  60.                  k:=pre[k];
  61.                end;
  62.                writeln('length=',dist[t]:0:0);
  63.                write(s);
  64.                for i:=length downto 1 do
  65.                   write('->',path[i]);
  66.                writeln;
  67.              end;
  68. end;{out}
  69. begin
  70.   init;
  71.   bellford;
  72.   out(s,t);
  73. end.

复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:45:33 | 显示全部楼层
输入一张无向图,指出该图中哪些结点对之间有路。该问题通常采用传递闭包的计算方法。
【输入】
    n(顶点数,1≤n≤20)
    e(边数,1≤e≤210)
    以下e行,每行为有边连接的一对顶点
【输出】
    k行,每行两个数,为存在通路的顶点对序号i,j(i<j)
 【输入样例】
6
5
1 5
1 6
2 3
4 6
5 6
 
【输出样例】
1 4
1 5
1 6
2 3
4 5
4 6
5 6
  1. program bibao_example;
  2. const
  3.   maxv=20;
  4. var
  5.   link,longlink:array[1..maxv,1..maxv] of boolean;
  6.   v,e,k,i,j:integer;
  7. procedure init;
  8.   begin
  9.     assign(input,'bibao.in');
  10.     reset(input);
  11.     assign(output,'bibao.out');
  12.     rewrite(output);
  13.     fillchar(longlink,sizeof(longlink),0);
  14.     fillchar(link,sizeof(link),0);
  15.     readln(v);
  16.     readln(e);
  17.     for k:=1 to e do
  18.      begin
  19.       readln(i,j);
  20.       link[i,j]:=true;            {因为没有权,所以有布尔型表示连通关系,能提高运算速度}
  21.       link[j,i]:=true;
  22.      end;
  23.   end;{init}
  24. procedure bibao;
  25.   begin
  26.     longlink:=link;
  27.     for k:=1 to v do                {枚举中间顶点}
  28.       for i:=1 to v do              {枚举所有顶点对}  
  29.         for j:=1 to v do            {计算顶点i和顶点j的连通情况}
  30.            longlink[i,j]:=longlink[i,j] or (longlink[i,k] and longlink[k,j]);
  31.   end;{bibao}
  32. procedure out;
  33.   begin
  34.    for i:=1 to v-1 do
  35.     for j:=i+1 to v do
  36.       if longlink[i,j]
  37.         then writeln(i,' ',j);
  38.   end;{out}
  39. begin{main}
  40.   init;
  41.   bibao;
  42.   out;
  43.   close(input);
  44.   close(output);
  45. end.
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:46:41 | 显示全部楼层
在一张顶点带权的无向图中,计算含顶点数最多的一个连通分支和顶点权和最大的连通分支。
【输入】
    n(顶点数,1≤n≤20)
    以下n行,其中第i行是顶点i的权
    e(边数,1≤e≤210)
    以下e行,每行为有边连接的一对顶点
【输出】
    含顶点数最多的一个连通分支
    顶点权和最大的一个连通分支
 【输入样例】
6
2
10
20
8
5
7
5
1 5
1 6
2 3
4 6
5 6
                           
【输出样例】
1->5->6->4->
2->3->
  1. program liantong_example;
  2. const
  3.   maxv=20;
  4. var
  5.   link,longlink:array[1..maxv,1..maxv] of boolean;
  6.   f:array[1..maxv] of boolean;
  7.   w:array[1..maxv] of integer;
  8.   v,e,k,i,j,s,best,besti,max,maxk:integer;
  9. procedure init;
  10.   begin
  11.    assign(input,'liantong.in');
  12.    reset(input);
  13.    assign(output,'liantong.out');
  14.    rewrite(output);
  15.    fillchar(longlink,sizeof(longlink),0);
  16.    fillchar(link,sizeof(link),0);
  17.    readln(v);
  18.    for i:=1 to v do
  19.      readln(w[i]);
  20.    readln(e);
  21.    for k:=1 to e do
  22.      begin
  23.        readln(i,j);
  24.        link[i,j]:=true;
  25.        link[j,i]:=true;
  26.      end;
  27.   end;{init}
  28. procedure bibao;
  29.   begin
  30.     longlink:=link;
  31.     for k:=1 to v do
  32.       for i:=1 to v do
  33.        for j:=1 to v do
  34.         longlink[i,j]:=longlink[i,j] or (longlink[i,k] and longlink[k,j]);
  35.   end;{bibao}
  36. procedure dfs(i:integer);         {深度优先搜索,用于输出路径}
  37.   begin
  38.     write(i,'->');
  39.     f[i]:=true;
  40.     for j:=1 to v do
  41.       if (not f[j]) and longlink[i,j]
  42.          then dfs(j);
  43.   end;{dfs}
  44. begin{main}
  45.   init;
  46.   bibao;
  47.   for i:=1 to v do
  48.     begin
  49.       k:=0;s:=0;
  50.       for j:=1 to v do          {计算顶点i所在连通分支中的顶点总数和顶点的权和}
  51.         if longlink[i,j]
  52.           then begin
  53.                  k:=k+1;
  54.                  s:=s+w[j];
  55.                end;
  56.         if k>best                {求出顶点数的最大值}
  57.             then begin
  58.                    best:=k;
  59.                    besti:=i;
  60.                  end;
  61.         if s>max                 {求出顶点权和的最大值}
  62.             then begin
  63.                    max:=s;
  64.                    maxk:=i;
  65.                  end;
  66.         if k=v then break;
  67.       end;
  68.    fillchar(f,sizeof(f),false);  {结点是否访问数组初始化}
  69.    dfs(besti);
  70.    writeln;
  71.    fillchar(f,sizeof(f),false);
  72.    dfs(maxk);
  73.   close(input);
  74.   close(output);
  75. end.
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:47:37 | 显示全部楼层
所谓拓扑序列,就是有向图的最长路径问题,如果图中存在环,则最长路径是无法求得的,所以有拓扑序列的有向图不可以存在环。具体定义如下:
    给出有向图G=(V,E),若结点的线形序列V1,V2,...Vn满足条件:对于i,j(1≤j<i≤n),Vi和Vj之间没有边。求线形序列V1,V2,...Vn的过程就称为拓扑排序,这个线形序列就称为拓扑序列。
【拓扑排序主要思想】
有向图可以拓扑排序的条件是:图中没有环。
具体方法:
⑴ 从图中选择一个入度为0的点加入拓扑序列。
⑵ 从图中删除该结点以及它的所有出边(即与之相邻点入度减1)。
反复执行这两个步骤,直到所有结点都已经进入拓扑序列。

【实例:士兵排队问题】
有n个士兵(1≤n≤26),依次编号为A,B,C,...,队列训练时,指挥官要把一些士兵从高到矮排成一行。但现在指挥官不能直接获得每个人的身高信息,只能获得“p1比p2高”这样的比较结果,记作(p1>p2)。例如A>B,B>D,F>D,对应的排队方案有三个:AFBD,FABD,ABFD
【输入】
    k行,每行a b,表示a>b
【输出】
    一个可行的排队方案
【输入样例】
A B
B D
F D 

【输出样例】
ABFD
 
  1. program soldier_sort;
  2. var
  3.   w:array['A'..'Z','A'..'Z'] of 0..1;
  4.   d:array['A'..'Z'] of integer;         {记录顶点入度的数组}
  5.   s:set of 'A'..'Z';
  6.   a,b,ch:char;
  7.   m,n:string;
  8.   i,j,k:integer;
  9. begin
  10.   assign(input,'tuopu.in');
  11.   reset(input);
  12.   assign(output,'tuopu.out');
  13.   rewrite(output);
  14.   s:=[];
  15.   while not eof(input) do
  16.     begin
  17.      readln(a,ch,b);
  18.      s:=s+[a,b];        {计算士兵名集合}
  19.      w[a,b]:=1;
  20.      d[b]:=d[b]+1;      {累计顶点b的入度}
  21.     end;
  22.   m:='';
  23.   for a:='A' to 'Z' do
  24.   if a in s
  25.     then m:=m+a;        {产生士兵名字符集}
  26.   k:=length(m);         {求得士兵人数}
  27.   n:='';                {拓扑序列初始为空}
  28.   for i:=1 to k do
  29.     begin
  30.      j:=1;
  31.      while (d[m[j]]>0) and (j<=k) do   {搜索第i个入度为0的士兵的顶点序号j}
  32.          j:=j+1;
  33.      if j>k                            {若不存在入度为0的顶点,则无法拓扑排序失败}
  34.        then begin
  35.              writeln('Fault!');  
  36.              break;
  37.             end;
  38.      n:=n+m[j];         {入度为0的顶点进入拓扑序列n}
  39.      a:=m[j];           {删去顶点j}
  40.      d[a]:=maxint;
  41.      for j:=1 to k do   {与a相连的顶点入度减1}
  42.      if w[a,m[j]]>0
  43.         then d[m[j]]:=d[m[j]]-1;
  44.    end;{for}
  45.   writeln(n);
  46.   close(input);
  47.   close(output);
  48. end.
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-25 12:48:42 | 显示全部楼层
某大学准备在校园网中构建校园网络,已知在校园网中选好了N(N<1000)个点,并准备在这些点安装网络设备和电脑。若要将N个点互相连接起来,问怎样布线才能使得总距离最短,两点间的布线长度等于这两个点的几何距离。
【输入】network.in
输入文件的第一行为一个正整数N(1≤N≤100)。
接下来N行,每行2个数U,V ,表示坐标。
【输出】network.out
输出最短路径距离(保留两位小数)

【样例数据】  
【输入】
5
0 0
0 1
0 -1
1 0
-1 0
【输出】
4.00

参考程序查看
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-19 14:24 , Processed in 0.065705 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表