动态规划(游船费用问题)

       大致题意为:从上游到下游有很多游船停靠站点。姑且设定为StopStation(0)(这个站点为起始站点),StopStation(1),StopStation(2)......每个站点自上而下分

布。其中,每两个站点之间的行驶费用是不同的。现在问如果从StopStation(0)起始点,坐船到下游最后一个站点,那么,求出花费的最小代价。

      这个问题的求解主要依靠动态规划。而动态规划是从下而上的算法基础。

                          0    (i=j)

   f[i,j](min)=

                          f[i,k](min) +f[k,j](min) (k<j)

      f[i,j](min)表示从站点i到j的最小费用。通过公式,很容易进行想到 利用同样的公式再次求解f[i,k](min),f[k,j](min)。然后就像剥香蕉一样,一层一层往里面剥。所以,当求

得最底层数之后,再重新往上层一次一次遍回溯,从而求得最终 f[i,j](min)最小费用。

     

 1 #include<iostream>
 2 using namespace std;
 3 const int Max = 100;
 4 ////
 5 
 6 //利用动态规划,自底向上,参照矩阵乘法开销最小问题
 7 
 8 ///
 9 int nn[Max][Max],rr[Max][Max],money[Max][Max];              //rr[Max][Max]记录两站点之间花费,如rr[i][j]表示站点i到j站点之间的花费
10 int i,j,k,m;
11 void PrintMoney(int rr[Max][Max],int mm[Max][Max],int nn)   
12 { 
13   int MoneyMin=0;                                          //先将MoneyMin初始化为0
14 
15   for(i=0;i<nn;i++)                                                                       
16      for(j=i+1;j<=nn;j++)         
17          rr[i][j] = mm[i][j];                                                    
18 
19   for(i=0;i<=nn;i++)                                       //i站点到i站点花费初始化为0
20       rr[i][i] = 0; 
21      
22   for(i=2;i<=nn;i++)                                       //这个for语句,主要是用来作为间距大小,从1开始,直到间距大小为nn(起始站点到最后一个站点为最大距离)
23   { 
24      for(j=0;j<=nn-i;j++)                                  //第2个for语句,确定站点j到j+i站点之间的花费
25      { 
26        MoneyMin = rr[j][j+i];                              //先初始化   
27        for(k=j+1;k < j+i;k++)                             
28        {
29          if(MoneyMin > rr[j][k]+rr[k][j+i])  
30              MoneyMin = rr[j][k]+rr[k][i+j];               //确定公式中k的最佳位置,即MoneyMin值为最小时
31 
32          rr[j][j+i] = MoneyMin;                            //确定了站点j到站点j+i的最小花费(由于是自底向上计算,所以总是从用最小值去求较大区间的最小值
33        }
34      }
35   }
36   return ;
37 }
38 
39 
40 int main()
41 {
42 int n,a;
43 while(cin>>n)
44 {
45  if(n==0)
46    break;
47  else
48  {
49    for(i=0;i<n;i++)
50        for(j=i+1;j<=n;j++)  
51        {
52         cin>>a;
53         rr[i][j] = a;
54        }
55 
56  }
57 PrintMoney(money,rr,n);  
58 cout<<money[0][n];  
59 
60 }
61 
62 return 0;
63 }


      输入时,用 

               for(i=0;i<n;i++)
                         for(j=i+1;j<=n;j++)

      每行数字分别表示表示:S[0]~S[1],S[2]....S[n],

                                     S[1]~S[2].....S[n],

                                     S[2]~S[3]......S[n] 之间的花费。

     最后一行表示结果从S[0]到S[3]的最小花费。

     数据结果:

     

         引用请注明出处http://www.cnblogs.com/Su-30MKK/archive/2012/09/17/2688551.html,谢谢合作!

    

 

     

    

转载于:https://www.cnblogs.com/Su-30MKK/archive/2012/09/17/2688551.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值