zoukankan      html  css  js  c++  java
  • 【NOIP2014】飞扬的小鸟

    Flappy Bird 是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败。

    为了简化问题,我们对游戏规则进行了简化和改编:

    1. 游戏界面是一个长为 nn,高为 mm 的二维平面,其中有 kk 个管道(忽略管道的宽度)。
    2. 小鸟始终在游戏界面内移动。小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成。
    3. 小鸟每个单位时间沿横坐标方向右移的距离为 11,竖直移动的距离由玩家控制。如果点击屏幕,小鸟就会上升一定高度 XX,每个单位时间可以点击多次,效果叠加;如果不点击屏幕,小鸟就会下降一定高度 YY。小鸟位于横坐标方向不同位置时,上升的高度 XX 和下降的高度 YY 可能互不相同。
    4. 小鸟高度等于 00 或者小鸟碰到管道时,游戏失败。小鸟高度为 mm 时,无法再上升。

    现在,请你判断是否可以完成游戏。如果可以,输出最少点击屏幕数;否则,输出小鸟最多可以通过多少个管道缝隙。

    输入格式

    第 11 行有 33 个整数 n,m,kn,m,k,分别表示游戏界面的长度,高度和水管的数量,每两个整数之间用一个空格隔开;

    接下来的 nn 行,每行 22 个用一个空格隔开的整数 XX 和 YY,依次表示在横坐标位置 0n10∼n−1 上玩家点击屏幕后,小鸟在下一位置上升的高度 XX,以及在这个位置上玩家不点击屏幕时,小鸟在下一位置下降的高度 YY。

    接下来 kk 行,每行 33 个整数 P,L,HP,L,H,每两个整数之间用一个空格隔开。每行表示一个管道,其中 PP 表示管道的横坐标,LL 表示此管道缝隙的下边沿高度,HH 表示管道缝隙上边沿的高度(输入数据保证 PP 各不相同,但不保证按照大小顺序给出)。

    输出格式

    共两行。

    第一行,包含一个整数,如果可以成功完成游戏,则输出 11,否则输出 00。

    第二行,包含一个整数,如果第一行为 11,则输出成功完成游戏需要最少点击屏幕数,否则,输出小鸟最多可以通过多少个管道缝隙。

    样例一

    input

    10 10 6
    3 9
    9 9
    1 2
    1 3
    1 2
    1 1
    2 1
    2 1
    1 6
    2 2
    1 2 7
    5 1 5
    6 3 5
    7 5 8
    8 7 9
    9 1 3
    
    

    output

    1
    6
    
    

    样例二

    input

    10 10 4
    1 2
    3 1
    2 2
    1 8
    1 8
    3 2
    2 1
    2 1
    2 2
    1 2
    1 0 2
    6 7 9
    9 1 4
    3 8 10
    
    

    output

    0
    3
    
    

    限制与约定

    对于 30%的数据:5n10,5m10,k=05≤n≤10,5≤m≤10,k=0,保证存在一组最优解使得同一单位时间最多点击屏幕 33 次;

    对于 50%的数据:5n20,5m105≤n≤20,5≤m≤10,保证存在一组最优解使得同一单位时间最多点击屏幕 33 次;

    对于 70%的数据:5n1000,5m1005≤n≤1000,5≤m≤100;

    对于 100%的数据:5n10000,5m10000k<n,0<X<m,0<Y<m,0<P<n,0L<Hm,L+1<H5≤n≤10000,5≤m≤1000,0≤k<n,0<X<m,0<Y<m,0<P<n,0≤L<H≤m,L+1<H。

    时间限制:1s1s

    空间限制:128MB

     

    首先想到设f[i][j]表示到第i第j所需要的最少点击屏幕次数。转移方程为

    f[ i ][ j ]=min{f[ i-1 ][ j - k*x[i-1] ] + k} (1<= k <= j/x) 上升——①

    f[ i ][ j ]=min{f[ i-1 ][ j + y[i-1] }  ( j + y[i-1] <= m) 下降

    显然,下降可以O(1)转移,主要问题在上升的转移。

    我们将上升的方程变一下:

    f[ i ][ j - x[i-1] ]=min{f[ i-1 ][ (j - x[i-1]) - (k-1)*x[i-1] ] + k -1} ——②

    这是 f[ i ][ j - x[i-1] ] 的转移。

    由 ② 化简可得:

    f[ i ][ j - x[i-1] ]=min{f[ i-1 ][ j - k*x[ i-1] ] + k -1}——③

    ①③消去f[ i-1 ][ j - k*x[ i-1] ]+k可得

    f[ i ][ j ]= f[ i ][ j - x[ i-1 ] ]+1

    于是就可以O(n*m)的时间内出解

     

     1 #include <map>
     2 #include <set>
     3 #include <cmath>
     4 #include <ctime>
     5 #include <queue>
     6 #include <stack>
     7 #include <cstdio>
     8 #include <string>
     9 #include <vector>
    10 #include <cstdlib>
    11 #include <cstring>
    12 #include <iostream>
    13 #include <algorithm>
    14 #define rg register
    15 using namespace std;
    16 #define ll long long
    17 
    18 inline int gi()
    19 {
    20     rg bool b=0;
    21     rg int r=0;
    22     char c=getchar();
    23     while(c<'0' || c>'9')
    24     {
    25         if(c=='-') b=!b;
    26         c=getchar();
    27     }
    28     while(c>='0' && c<='9')
    29     {
    30         r=r*10+c-'0';
    31         c=getchar();
    32     }
    33     if(b) return -r;
    34     return r;
    35 }
    36 
    37 const int inf = 2100000000, N = 10005, M = 1005;
    38 int n,m,q,x[N],y[N],f[N][M];
    39 bool b[N];
    40 struct data
    41 {
    42     int up,down;
    43 } da[N];
    44 
    45 int main()
    46 {
    47     freopen ("birda.in","r",stdin);
    48     freopen ("birda.out","w",stdout);
    49     int i,p,j,k,cnt,ans;
    50     n=gi(), m=gi(), q=gi();
    51     for (i=0; i<n; i++) x[i]=gi(), y[i]=gi();
    52     for (i=1; i<=n; i++) da[i].down=0, da[i].up=m+1;
    53     for (i=0; i<q; i++) p=gi(), da[p].down=gi(), da[p].up=gi();    //一定要加,不然会影响到第65行的循环枚举 
    54     for (i=1; i<=n; i++) for (j=0; j<=m; j++) f[i][j]=inf;    //初始化。0位置除地面外都为0
    55     f[0][0]=inf;
    56     for (i=1; i<=n; i++)
    57     {
    58         for (j=x[i-1]; j<=m; j++)
    59         {
    60             f[i][j]=min(f[i][j],f[i-1][j-x[i-1]]+1), f[i][j]=min(f[i][j],f[i][j-x[i-1]]+1);  //更新解,先不考虑水管 
    61             if (j == m)        //特殊判断 j==m 的情况,因为不能超过 m ,所以有多种转移 
    62                 for (k=m-x[i-1]; k<=m; k++)
    63                     f[i][j]=min(f[i][j],f[i-1][k]+1), f[i][j]=min(f[i][j],f[i][k]+1);
    64         }
    65         for (j=da[i].down+1; j<da[i].up; j++)  //处理下落,必须是合法的 
    66             if (j+y[i-1] <= m)
    67                 f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]);
    68         for (j=1; j<=da[i].down; j++) f[i][j]=inf;  //考虑水管,去掉不合法的解 
    69         for (j=m; j>=da[i].up; j--) f[i][j]=inf;
    70     }
    71     cnt=q,ans=inf;
    72     for (i=n; i>=1; i--)
    73     {
    74         for (j=1; j<=m; j++) ans=min(ans,f[i][j]);  //若 ans 有值则代表能到达。 
    75         if (ans < inf) break;
    76         if (da[i].up <= m) cnt--;  //  da[i].up <= m 才是真水管 
    77     }
    78     if (cnt == q) printf("1
    %d
    ",ans);
    79     else printf("0
    %d
    ",cnt);
    80     return 0;
    81 }

     感谢nfy_algorithm提出宝贵的建议。

  • 相关阅读:
    动态生成 Excel 文件供浏览器下载的注意事项
    JavaEE 中无用技术之 JNDI
    CSDN 泄露用户密码给我们什么启示
    刚发布新的 web 单点登录系统,欢迎下载试用,欢迎提建议
    jQuery jqgrid 对含特殊字符 json 数据的 Java 处理方法
    一个 SQL 同时验证帐号是否存在、密码是否正确
    PostgreSQL 数据库在 Windows Server 2008 上安装注意事项
    快速点评 Spring Struts Hibernate
    Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
    解决 jQuery 版本升级过程中出现 toLowerCase 错误 更改 doctype
  • 原文地址:https://www.cnblogs.com/y142857/p/7134366.html
Copyright © 2011-2022 走看看