[HDU] 2059 龟兔赛跑 有点暴力性质的dp

View Code
#include<iostream>
//#include<math.h>
//#include<algorithm>
//#include<queue>
//#include<stack>
using namespace std;
int const MAX =0x3f3f3f3f;
 
struct state
{
    int remainDriving;
    int divingDist;
    int fDist;
    double time;
};
int main()
{
    int totalLengh;
    int chargerCount,drivingDist,chargingDuration;
    int r_speed,t_dSpeend,t_fSpeed;
    int dist[102];
    while(scanf("%d",&totalLengh)!=EOF)
    {
         state dp[102][102];
         memset(dp,0,sizeof(dp));
         scanf("%d %d %d",&chargerCount,&drivingDist,&chargingDuration);
         scanf("%d %d %d",&r_speed,&t_dSpeend,&t_fSpeed );
         for(int i=1;i<=chargerCount;i++)
            scanf("%d",&dist[i]);
         dist[0]=0;
         dist[chargerCount+1]=totalLengh;
         dp[0][0].divingDist=0;
         dp[0][0].fDist=0;
         dp[0][0].remainDriving = drivingDist;
         dp[0][0].time=0.0;
         for(int i = 1;i<=chargerCount+1;i++)
         {
             double minTime = MAX+0.0;
             int minIndex;
             for(int j=0;j<i;j++)
             {
                 if(dp[j][i-1].remainDriving <= dist[i]-dist[i-1])
                 {
                     dp[j][i].divingDist = dp[j][i-1].remainDriving;
                     dp[j][i].fDist = dist[i]-dist[i-1]-dp[j][i-1].remainDriving;
                     dp[j][i].remainDriving = 0; 
                 }
                 else
                 {
                     dp[j][i].divingDist = dist[i]-dist[i-1];
                     dp[j][i].fDist = 0;
                     dp[j][i].remainDriving = dp[j][i-1].remainDriving -(dist[i]-dist[i-1]); 
                 }
                 dp[j][i].time = dp[j][i-1].time + (double)dp[j][i].divingDist/(double)t_dSpeend + (double)dp[j][i].fDist/(double)t_fSpeed;
                 if(minTime>dp[j][i].time)
                 {
                    minTime = dp[j][i].time;
                    minIndex = j;
                 }
             }
             dp[i][i].divingDist = dp[minIndex][i].divingDist;
             dp[i][i].fDist = dp[minIndex][i].fDist;
             dp[i][i].time =  dp[minIndex][i].time+(double)chargingDuration;
             dp[i][i].remainDriving = drivingDist;
         }
         double temp = (double)MAX;
     
         for(int i=0;i<chargerCount+1;i++)
         {
             if(dp[ i][chargerCount+1].time<temp)
                 temp = dp[i][chargerCount+1].time;
         }
         double r_t = (double)totalLengh/(double)r_speed;
         if(r_t>temp)
             cout<<"What a pity rabbit!"<<endl;
         else
             cout<<"Good job,rabbit!"<<endl;
            
    }
    return 0;
} 

 

 

 

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2059

方法:设F(i,n)  (0<=i<n)来表示当到达第n个加油站的时候,在前面的n-1个加油站中的第i个加油站加油其他加油站不加油的前进情况,i的0表示是刚出发的那个位子,把那个位子也模拟成一个加油站,当然它只有一个选择,那就是加满了油的。这些前进情况包含几个信息:从上一个加油站到此骑车前进的距离drivingDist,从上一个加油站到此步行前进的距离fDist,从开始到此一共花的时间time以及当前还剩余多少距离可以骑车前进remainDriving。

当i==n的时候,这个表示成在该站要加油,这个时候,需要消耗的时间当然是以上状态中最快的那个时间加上加油的时间,因为不管以上状态还,还可以继续骑车的距离有多么不同,只要一加了油,都会同一继续骑车的剩余距离,那就是加满油的骑车前进距离。既然如此那当然选择以上状态中最快的一个F(fastest,n),这样的选择其实就会涵盖前面几个加油站加油还是不加油,是连续几个加油站都加油还是怎么这些组合可能的考虑,最后设置加油后的前进状态。设两个加油站k,j间的距离为S(k,j)

状态转移方程:

    {

      [  

         drivingDist = F(i,n-1).remainDriving >= S(n-1,n) ? S(n-1,n):  F(i,n-1).remainDriving,

         remainDriving = F(i,n-1).remainDriving >= S(n-1,n) ?  F(i,n-1).remainDriving-S(n-1,n):  0,

         fDist = F(i,n-1).remainDriving >= S(n-1,n) ?  0:S(n-1,n)-F(i,n-1).remainDriving,

         time =  F(i,n-1).time + drivingDist/骑车速度 + fDist/步行速度

      ], 0<=i<n;

F(i,n) =  [  

           除 time外的所有信息都和F(fastest,n) 的相同,

        time = Min({  F(i,n).time | 0<=i<n}) + 加油消耗时间

      ], i==n;

   }

而最后问题的解为:Min( {F(i,N).time | 1<=i<=N})

最后拿这个解去和兔子比速度。

感谢:细心,注意小数运算。

代码:

View Code
#include<iostream>
//#include<math.h>
//#include<algorithm>
//#include<queue>
//#include<stack>
using namespace std;
int const MAX =0x3f3f3f3f;
 
struct state
{
    int remainDriving;
    int divingDist;
    int fDist;
    double time;
};
int main()
{
    int totalLengh;
    int chargerCount,drivingDist,chargingDuration;
    int r_speed,t_dSpeend,t_fSpeed;
    int dist[102];
    while(scanf("%d",&totalLengh)!=EOF)
    {
         state dp[102][102];
         memset(dp,0,sizeof(dp));
         scanf("%d %d %d",&chargerCount,&drivingDist,&chargingDuration);
         scanf("%d %d %d",&r_speed,&t_dSpeend,&t_fSpeed );
         for(int i=1;i<=chargerCount;i++)
            scanf("%d",&dist[i]);
         dist[0]=0;
         dist[chargerCount+1]=totalLengh;
         dp[0][0].divingDist=0;
         dp[0][0].fDist=0;
         dp[0][0].remainDriving = drivingDist;
         dp[0][0].time=0.0;
         for(int i = 1;i<=chargerCount+1;i++)
         {
             double minTime = MAX+0.0;
             int minIndex;
             for(int j=0;j<i;j++)
             {
                 if(dp[j][i-1].remainDriving <= dist[i]-dist[i-1])
                 {
                     dp[j][i].divingDist = dp[j][i-1].remainDriving;
                     dp[j][i].fDist = dist[i]-dist[i-1]-dp[j][i-1].remainDriving;
                     dp[j][i].remainDriving = 0; 
                 }
                 else
                 {
                     dp[j][i].divingDist = dist[i]-dist[i-1];
                     dp[j][i].fDist = 0;
                     dp[j][i].remainDriving = dp[j][i-1].remainDriving -(dist[i]-dist[i-1]); 
                 }
                 dp[j][i].time = dp[j][i-1].time + (double)dp[j][i].divingDist/(double)t_dSpeend + (double)dp[j][i].fDist/(double)t_fSpeed;
                 if(minTime>dp[j][i].time)
                 {
                    minTime = dp[j][i].time;
                    minIndex = j;
                 }
             }
             dp[i][i].divingDist = dp[minIndex][i].divingDist;
             dp[i][i].fDist = dp[minIndex][i].fDist;
             dp[i][i].time =  dp[minIndex][i].time+(double)chargingDuration;
             dp[i][i].remainDriving = drivingDist;
         }
         double temp = (double)MAX;
     
         for(int i=0;i<chargerCount+1;i++)
         {
             if(dp[ i][chargerCount+1].time<temp)
                 temp = dp[i][chargerCount+1].time;
         }
         double r_t = (double)totalLengh/(double)r_speed;
         if(r_t>temp)
             cout<<"What a pity rabbit!"<<endl;
         else
             cout<<"Good job,rabbit!"<<endl;
            
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/kbyd/p/3044801.html