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的花销。

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

  • 相关阅读:
    c#除掉字符串最后一个字符几种方法
    DateTime.Compare(t1,t2)比较两个日期大小
    图片如何存入数据库
    C#文本文件(.txt)读写
    【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
    【第四篇】ASP.NET MVC快速入门之完整示例(MVC5+EF6)
    【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)
    【第二篇】ASP.NET MVC快速入门之数据注解(MVC5+EF6)
    【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)
    总结用CoreText绘制文本时遇到的问题以及解决办法
  • 原文地址:https://www.cnblogs.com/xFANx/p/7404213.html
Copyright © 2011-2022 走看看