zoukankan      html  css  js  c++  java
  • UVA

    传送门

    题意:在一维的维度上,有一个间谍要从第1站到第n站。已知有从第1站到第n站的车与第n站开向第1站的车。间谍乘车到一个站时可以下车,若此时有车经过该站,他可以立即乘上该车。求保证间谍在T时刻可以到达第n站的前提下,不在车上(即在车站上等待)的最短时间。

    输入:多组数据

    第一行为n,第二行为T,第三行n-1个整数t1~tn-1(1<=t<=70),表示从ti到ti+1耗时

    第四行 M1表示从第1站到第n站的车的数量

    第五行 发车时间

    第六行 M1表示从第n站到第1站的车的数量

    第七行 发车时间

    输出:不能到达输出impossible,否则输出最短时间

    题解:在确定了车的方向与发车时间之后,我们知道最后的答案只与当前时间与所处的位置有关。由于我们只能在车站换乘,所以其实我们只需要考虑时间与当前处在哪个站。那么我们定义dp[i][j]表示时刻i,间谍处于j站,需要的最少等待时间。由于我们确定了T时刻处于第n站,那么我们逆推回来,最终得到的dp[0][1]即是答案。

    对于dp[i][j],间谍可以下车等待,或搭乘向右的车,或搭乘向左的车。对于这个,我们有一个数组来预处理出i时刻是否有车经过j站即可。

    总的复杂度时O(NT)

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define INF 0x3f3f3f3f
     6 #define MOD 1000000007
     7 using namespace std;
     8 typedef long long LL;
     9 
    10 const int maxn = 55;
    11 const int maxt = 255;
    12 int t[maxn];
    13 int dp[maxt][maxn];
    14 bool has_train[maxt][maxn][2];
    15 int N, T;
    16 int Case;
    17 
    18 void solve() {
    19     for (int i = 1; i <= N - 1; i++) dp[T][i] = INF;
    20     dp[T][N] = 0;
    21     for (int i = T - 1; i >= 0; i--) {
    22         for (int j = 1; j <= N; j++) {
    23             dp[i][j] = dp[i + 1][j] + 1;
    24             if (j < N && has_train[i][j][0] && i + t[j] <= T) {//搭乘向n的
    25                 dp[i][j] = min(dp[i][j], dp[i + t[j]][j + 1]);
    26             }
    27             if (j > 1 && has_train[i][j][1] && i + t[j - 1] <= T) {//搭乘向1的
    28                 dp[i][j] = min(dp[i][j], dp[i + t[j - 1]][j - 1]);
    29             }
    30         }
    31     }
    32     printf("Case Number %d: ", ++Case);
    33     if (dp[0][1] >= INF) printf("impossible
    ");
    34     else                 printf("%d
    ", dp[0][1]);
    35 }
    36 
    37 int main(int argc, const char * argv[]) {
    38     while (scanf("%d", &N), N) {
    39         memset(has_train, 0, sizeof(has_train));
    40         scanf("%d", &T);
    41         for (int i = 1; i < N; i++) scanf("%d", &t[i]);
    42         int to_right; scanf("%d", &to_right);
    43         for (int i = 1; i <= to_right; i++) {
    44             int time; scanf("%d", &time);
    45             int s = 1;
    46             while (time <= T && s < N) {
    47                 has_train[time][s][0] = 1;
    48                 time += t[s];
    49                 s++;
    50             }
    51         }
    52         int to_left; scanf("%d", &to_left);
    53         for (int i = 1; i <= to_left; i++) {
    54             int time; scanf("%d", &time);
    55             int s = N - 1;
    56             while (time <= T && s >= 1) {
    57                 has_train[time][s + 1][1] = 1;
    58                 time += t[s];
    59                 s--;
    60             }
    61         }
    62         solve();
    63     }
    64     return 0;
    65 }
    View Code

     感觉应该从这道题学的就是只需要记录i时刻在哪个站就可以获得足够的信息,而没必要存储每个位置,而且记录在哪个站还更容易设计转移状态

    同样的,UVA437,将的有n种立方体,三条边分别为x,y,z,每种都有无数个。要求叠放时一个立方体的底面长宽严格小于其下方的底面长宽。

    这显然是一个DAG图,对于每个立方体,存储它的三种摆放状态即可,但是如果我们直接存储边长,需要max_len *max_len的花销,显然会有不少的浪费。其实我们只需要定义这三种摆放方式,然后存储摆放方式和使用的立方体序号即可。例如按照第几长的边作高区别摆放的状态,这样只需要3*n的花销。

    存储下标是一种很有用的方式。因为我们可以通过下标读取数值。这样有时我们可以利用更小的空间来获得更多的信息。还有就是有些要求不能重复的题目,如果你直接存储数值,难以判断是否重复,因为有可能不同的物品有同样的部分特征,这时存储下标有更好的区别效果,输出时按下标访问,也很方便。

  • 相关阅读:
    poj 2728 Desert King
    uva 439 Knight Moves
    hdu 1875 畅通工程再续
    scau实验题 8600 骑士周游问题(有障碍物)
    scau实验题 8596 Longest Ordered Subsequence
    poj 1679 The Unique MST
    uva 527 Oil Deposits
    poj 2533 Longest Ordered Subsequence
    .net 程序员 java 开发入门
    Collation conflict occur at operation on User define funtion & table's column
  • 原文地址:https://www.cnblogs.com/xFANx/p/7404213.html
Copyright © 2011-2022 走看看