• HDU 2059:龟兔赛跑


    题意

    一条直线上有n个充电站(告诉你位置),乌龟刚开始有满电的电车,能开c距离,电动速度vt1,没电后脚踩速度vt2,到充电站可以选择充电,充电时间为t。

    直线长l, 兔子速度为vr, 问乌龟有没有可能赢。

    类型:

    DP

    思路:

    my:

    类似cf一题的思路

    大体思路:把一段路合理分割,就可以把重叠的区间分开,然后就可以算出每段路的最小花费。最后寻找最短的拼接方法就好了。

    首先状态压缩,节点为所有充电站的点和他们+c的点(另外:包含0和c)

    然后对于每个点i,算出他们到之前的某个点j的最小花费cost[i][j]

    然后 设dp[i]为到i号节点所需最小时间

    状态转移为 dp[i] = min(dp[j] + cost[i][j])  (j = 0,1...i-1)

    网:

    dp[i]为从0到第i个充电站的最短时间(起点和终点都看做一个充电站)

    dp[i] = min(dp[j] + cost[i][j]) (j = 0,1...i-1)

    其中cost[i][j] 表示从j充电站 充满电 然后一路不停到i的时间。

    应该说,网上的方法是我的方法在特殊情况下的解。

    在状态转移上的差别在于,我的cost[i][j]表示j到i的最小花费

    而网上的方法则是某个特定花费。

    这个特定花费得到的思路是,当前状态,必然是由之前最后一个充电站来的。

    抽象之,

    我:当前状态的最优情况 由 之前某个状态 通过最优转移 得到。

    网:当前状态的最优情况 必然由 之前某个状态 通过某种转移 得到。

    简单的说:

    网上这种思路的关键,就是找到,当前状态,必然是怎么来的。

    寻找时需要置身于这种状态,然后想想他 必然 是怎么来。

    如果没有必然,就是说怎么都有可能,那只能用最优转移的思路了。

    收获总结

    dp时

    先找 必然转移 关系。

    未果可以使用 最优转移 思路。

    代码

    /*************************************************************************
        > File Name:    hd2059.cpp
        > Author:       Shine
        > Created Time: 2013-06-26 上午 9:16:42
        > QuestionType: DP,离散化
        > Way: ...
        > Submit: 1A
        > Gain: 最优转移 和 必然转移
        > Experience: 优先考虑 必然转移 。因为最优转移很不好想。
     ************************************************************************/
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int p[120];
    int zip[300];
    double zipGraph[300][300];
    double dp[300];
    
    
    inline double min(const double &a, const double &b) { return a < b ? a : b; }
    
    double dfs(int i) {
        if (dp[i] != -1) return dp[i];
        double min = 9999999;
        //int finalj = -1;
        for (int j = i-1; j >= 0; j--) {
            //if (i <= j) cout<<"zipGraph reading ERROR! (i = "<<i<<", j = "<<j<<")"<<endl;
            if (dfs(j)+zipGraph[i][j] < min) {
                min = dfs(j) + zipGraph[i][j];
                //finalj = j;
            }
        }
        //cout<<"i = "<<i<<" finalj = " << finalj << endl;
        return dp[i] = min;
    }
            
    int main() {
        int l, n, c, t, vr, vt1, vt2;
        while(cin >> l >> n >> c >> t >> vr >> vt1 >> vt2) {
            p[0] = 0;
            for (int i = 1; i <= n; i++) { cin >> p[i]; }
    
            //compress
            int tmp[300];
            int i;
            for (i = 0; i <= n; i++) tmp[i+n+1] = (tmp[i] = p[i]) + c;
            sort(tmp, tmp+2*(n+1));
    
            //for (int i = 0; i < 2*n+2; i++) { cout<<" "<<tmp[i]; }cout<<endl; 
    
            zip[0] = tmp[0];
            int zipp = 1;
            for (int i = 1; i < 2*(n+1); i++) {
                if (tmp[i] == tmp[i-1]) continue;
                if (tmp[i] >= l) break;
                zip[zipp++] = tmp[i];
            }
            zip[zipp++] = l;
    
            //for (int i = 0; i < zipp; i++) cout<<" "<<zip[i];
            //cout<<endl;
    
            //build zipGraph
            for (int i = zipp-1; i >= 0; i--) {
                for (int j = i-1; j >= 0; j--) {
                    //if(i <= j) cout<<"zipGraph reading ERROR! (i = "<<i<<", j = "<<j<<")"<<endl;
                    zipGraph[i][j] = (double)(zip[i] - zip[j])/vt2;
                }
            }
    
            
            int j = 0;
            //for (int i = j+1; i < zipp && zip[i] <= zip[j]+c; i++) {
            //    if (i <= j) cout<<"zipGraph reading ERROR! (i = "<<i<<", j = "<<j<<")"<<endl;
            //    zipGraph[i][j] = min(zipGraph[i][j], (double)(zip[i]-zip[j])/vt1);
            //}
    
            for (int pp = 0; pp <= n; pp++) {
                for (; zip[j] != p[pp]; j++);
                for (int i = j+1; i < zipp && zip[i] <= zip[j]+c; i++) {
                    //if (i <= j) cout<<"zipGraph reading ERROR! (i = "<<i<<", j = "<<j<<")"<<endl;
                    zipGraph[i][j] = min(zipGraph[i][j], (double)(zip[i]-zip[j])/vt1 + t*(j != 0));
                }
            }
    
            //dfs find answer
            dp[0] = 0;
            for (int i = 1; i < zipp; i++) dp[i] = -1;
    
            //cout<<"( "<<dfs(zipp-1)<<" "<<(double)l/vr<<" )"<<endl;
    
            if (dfs(zipp-1) < (double)l/vr) cout << "What a pity rabbit!" << endl;
            else cout << "Good job,rabbit!" << endl;
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Python基础篇【第十一篇】:正则表达式之计算器
    Python基础篇【第十篇】:正则表达式
    Python基础篇【第九篇】:剖析装饰器
    Python基础篇【第八篇】:剖析递归函数
    Python基础篇【第七篇】:文件操作
    Python基础篇【第六篇】:函数补充
    Python基础篇【第五篇】:sed和函数
    TCP/IP详解之:Ping程序、Traceroute程序
    TCP/IP详解之:ICMP协议
    TCP/IP详解之:ARP协议 和 RARP协议
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3156370.html
Copyright © 2020-2023  润新知