【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,依次表示在横坐标位置 0~n?10~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%的数据:5≤n≤10,5≤m≤10,k=05≤n≤10,5≤m≤10,k=0,保证存在一组最优解使得同一单位时间最多点击屏幕 33 次;

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

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

对于 100%的数据:5≤n≤10000,5≤m≤1000,0≤k<n,0<X<m,0<Y<m,0<P<n,0≤L<H≤m,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] ]

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\n%d\n",ans);
79     else printf("0\n%d\n",cnt);
80     return 0;
81 }
时间: 2024-10-12 23:34:29

【NOIP2014】飞扬的小鸟的相关文章

noip2014飞扬的小鸟

飞扬的小鸟 题目链接 题意: 一个二维平面,长为\(n\),宽为\(m\),其中有\(k\)个管道,小鸟从最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成. 小鸟每个单位时间沿着\(x\)轴向右移动一个单位距离,小鸟在从\(i\)移动到\(i +1\)时,玩家可以选择是否点击屏幕(可以点击多次),若不点击,小鸟将下降\(y_i\)单位距离,若点击\(j\)次,小鸟的上升距离为\(j\times x_i\). 当小鸟碰到管壁或纵坐标等于\(0\)时,游戏结束.小鸟的高度可以不停上升,但最

[NOIP2014] 飞扬的小鸟

题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败. 为了简化问题,我们对游戏规则进行了简化和改编: 游戏界面是一个长为n ,高为 m 的二维平面,其中有k 个管道(忽略管道的宽度). 小鸟始终在游戏界面内移动.小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成. 小鸟每个单位时间沿横坐标方向右移的距离为1 ,竖直移动

NOIP2014 飞扬的小鸟(Flappy Bird)

题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败. 为了简化问题,我们对游戏规则进行了简化和改编: 游戏界面是一个长为n ,高为 m 的二维平面,其中有k 个管道(忽略管道的宽度). 小鸟始终在游戏界面内移动.小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成. 小鸟每个单位时间沿横坐标方向右移的距离为1 ,竖直移动

NOIP2014飞扬的小鸟[DP][WRONG]

坑人啊朴素的dp 75分 用了完全背包才是80分,结果普遍偏小 为什么啊啊啊啊啊 等以后再写一遍吧 //80 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=10005,M=1005,INF=1e9; int n,m,k, x,y,p,ll,hh; int up[N],down[N],l[N],h[N], has[N]; int f[N][M];

[ NOIP ][ NOIP_2014D1T3 ][ 动态规划 ] 飞扬的小鸟

飞扬的小鸟(Flappy Bird) 描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败. 为了简化问题,我们对游戏规则进行了简化和改编: 游戏界面是一个长为 n,高为 m 的二维平面,其中有k 个管道(忽略管道的宽度). 小鸟始终在游戏界面内移动.小鸟从游戏界面最左边 任意整数高度位置出发,到达游戏界面最右边时,游戏完成. 小鸟每个单位时间沿

luogu P1941 飞扬的小鸟

二次联通门 : luogu P1941 飞扬的小鸟 /* luogu P1941 飞扬的小鸟 dp 向上飞是完全背包,向下掉就是01背包 分情况讨论一下 最后合并一下 */ #include <cstdio> #include <iostream> #include <cstring> const int BUF = 123123123; char Buf[BUF], *buf = Buf; inline void read (int &now) { for (

洛谷 【P1941】飞扬的小鸟

P1941 飞扬的小鸟 题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败. 为了简化问题,我们对游戏规则进行了简化和改编: 游戏界面是一个长为n ,高为 m 的二维平面,其中有k 个管道(忽略管道的宽度). 小鸟始终在游戏界面内移动.小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成. 小鸟每个单位时间沿横坐标方向右

codevs 3729 飞扬的小鸟 x

3729 飞扬的小鸟 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 输入描述 Input Description 输出描述 Output Description 输出文件名为 bird.out. 共两行. 第一行,包含一个整数,如果可以成功完成游戏,则输出 1,否则输出 0. 第二行,包含一个整数,如果第一行为 1,则输出成功完成游戏需要最少点击屏幕数, 否则,输出小鸟最多可以通过多少个管道缝隙. 样例输入 Sample In

洛谷P1941 飞扬的小鸟 动态规划

洛谷P1941 飞扬的小鸟 动态规划 这道题主要要注意一下飞到m以上之后高度还是 m 这个就要在判断一下 比较直接暴力的动归 是 O(N^3) f[ i ][ j ] 到 i ,j 这个位置 所需要的最少点击次数 如果不能到,就是无限大 f[ i ][ j ] = min(f[ i-1 ][ j-up[i-1] ] +1 , f[ i-1 ][ j+down[i-1] ] ) 因为可以向上飞无限次 这其实就相当于是无限背包 然后 f[ i ][ j ] 就可以从 f[ i ][ j-up[ i-