zoukankan      html  css  js  c++  java
  • A Spy in the Metro UVA-1025(dp)

    vjudge链接

    原题链接

    • 分析

    我的第一个动归题哈哈,一开始甚至写成了 dfs 。动归题其实都可以用 dfs ,但是太多的重复计算会导致超时。这个题其实可以以时间为主线,通过两层循环填表来解决。紫书上是逆推的,其实顺推和逆推都可以,逆推更方便。

    刚开始以为 “Trainsmove in both directions: from the first station to the last station and from the last station back to the first station.” 是说车到达终点站后会折返,事实上只是说两个方向的车行驶方向不同而已。车到达终点站后不会折返。

    • AC 代码

    顺推:

    /*
     *lang C++ 5.3.0
     *user Weilin_C
    */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    int main()
    {
        int N, T, station[50], c = 0;
        int rightT[205][25], leftT[205][25], tr, tl;
        int dp[500][50];
    
        while (scanf("%d", &N) && N) {
            int t;
            memset(rightT, 0, sizeof(rightT));
            memset(leftT, 0, sizeof(leftT));
            scanf("%d", &T);
            for (int i = 0; i < N-1; i++)
                scanf("%d", &station[i]);
                scanf("%d", &tr);
                for (int i = 0; i < tr; i++) {
                    scanf("%d", &t);
                    for (int ti = t, st = 0; ti <= T && st < N; st++) {
                        rightT[ti][st] = 1;
                        ti += station[st];
                    }
                }
                scanf("%d", &tl);
                for (int i = 0; i < tl; i++) {
                    scanf("%d", &t);
                    for (int ti = t, st = N-1; ti <= T && st > 0; st--) {
                        leftT[ti][st] = 1;
                        ti += station[st-1];
                    }
                }
    
                //初始化为比 T 大就行,也可以用 memset(dp, 1, sizeof(dp));
                for (int i = 0; i <= T; i++)
                    for (int j = 0; j <= N; j++)
                        dp[i][j] = T+1;
    
                dp[0][0] = 0;
                for (int i = 1; i <= T; i++) {
                    for (int j = 0; j < N; j++) {
                        dp[i][j] = dp[i-1][j] + 1;
                        if (j > 0 && i >= station[j-1] && rightT[i-station[j-1]][j-1]) { //有右向车到达
                            dp[i][j] = min(dp[i][j], dp[i-station[j-1]][j-1]);
                        }
                        if (j < N-1 && i >= station[j] && leftT[i-station[j]][j+1]) { //有左向车到达
                            dp[i][j] = min(dp[i][j], dp[i-station[j]][j+1]);
                        }
                    }
                }
    
                printf("Case Number %d: ", ++c);
                if (dp[T][N-1] > T) printf("impossible
    ");
                else printf("%d
    ", dp[T][N-1]);
        }
    
        return 0;
    }
    

    逆推和紫书上差不多:

                dp[T][N-1] = 0;
                for (int i = T-1; i >= 0; i--) {
                    for (int j = 0; j < N; j++) {
                        dp[i][j] = dp[i+1][j] + 1;
                        if (j < N-1 && i + station[j] <= T && rightT[i][j]) { //有右向车出发
                            dp[i][j] = min(dp[i][j], dp[i + station[j]][j+1]);
                        }
                        if (j > 0 && i + station[j-1] <= T && leftT[i][j]) { //有左向车出发
                            dp[i][j] = min(dp[i][j], dp[i + station[j-1]][j-1]);
                        }
                    }
                }
    
                printf("Case Number %d: ", ++c);
                if (dp[0][0] > T) printf("impossible
    ");
                else printf("%d
    ", dp[0][0]);
    

    by SDUST weilinfox
    原文链接:https://www.cnblogs.com/weilinfox/p/12559058.html

  • 相关阅读:
    读《构建之法》8、9、10章有感
    评论
    复利计算器(4)——jQuery界面美化、自动补全
    送给搭档的“汉堡”
    MFC之TreeCtrl控件使用经验总结
    MFC绘制图片闪烁详解
    MFC 网络编程中::connect返回-1问题
    C++网络编程之select
    C++关于Condition Variable
    Mutex 和 Lock
  • 原文地址:https://www.cnblogs.com/weilinfox/p/12559058.html
Copyright © 2011-2022 走看看