3. 飞扬的小鸟

(bird.cpp/c/pas)

【问题述】

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

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

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

现在,请你判断是否可以完成游戏。如果可以,输出最少点击屏幕数;否则,输出小鸟

最多可以通过多少个管道缝隙。

【输入】

输入文件名为 bird.in。

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

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

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

【输出】

输出文件名为bird.out。

共两行。

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

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

【输入输出样例1】

bird.in

bird.out

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

1

6

【输入输出样例2】

bird.in

bird.out

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

0

3

 

【输入输出样例说明】

如下图所示,蓝色直线表示小鸟的飞行轨迹,红色直线表示管道。

【数据范围】

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

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

对于70%的数据:5≤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<H。

【思路】

题目思路很简单,但是写起来总感觉不顺手。

状态转移方程:

D[i][j]=min{d[i-1][j+y[i-1], d[i-1][j-k*x[i-1]+k}

这里的k容易联想到完全背包的无限物品,类似的,不用去枚举k,改成d[i][j-x[i]]+1,它的意思其实就是累计。修改之后还需要注意由y划分子问题应该放在x之后,否则会造成决策叠加的效果。

J==m的特殊情况:注意到题目中说“小 鸟 高 度 为m时,无法再上升。”特殊处理:也是用累计的方法,d[i][j]=min(d[i][j],d[i][pos]+1) pos from [j-x[i-1],m] 由点成为了线段。

Fly失败:用一个flag,只要d[i][]全都为INF则问题不能求解,相应输出结束。

【代码】

 #include<iostream>
#define FOR(a,b,c) for(int a=(b);a<(c);a++)
using namespace std; const int INF=<<;
const int maxn = + , maxm = +;
int n,m,K;
int d[maxn][maxm];
int x[maxn],y[maxn],up[maxn],down[maxn]; int main() {
ios::sync_with_stdio(false); cin>>n>>m>>K;
FOR(i,,n) {
cin>>x[i]>>y[i];
up[i]=m+; down[i]=; //down=0 up=m+1
} up[n]=m+; down[n]=; FOR(i,,K) {
int p; cin>>p;
cin>>down[p]>>up[p];
}
FOR(i,,n+) FOR(j,,m+) d[i][j]=INF;
d[][]=INF;//d声明在全局变量自动清0 FOR(i,,n+) //i从1开始 到n结束
{
bool flag=true;
FOR(j,down[i]+,up[i]) { //这里写错过==
if(j-x[i-]>down[i-]) {
d[i][j]=min(d[i][j],d[i][j-x[i-]]+);
d[i][j]=min(d[i][j],d[i-][j-x[i-]]+);
}
if(j==m) FOR(pos,j-x[i-],j+) { //特殊情况特殊判断//注意不要写在上一个if里
d[i][j]=min(d[i][j],d[i][pos]+);
d[i][j]=min(d[i][j],d[i-][pos]+);
}
if(d[i][j]<INF) flag=false;
}
//求完关于x之后才能求y 否则x中的决策d[i][j-x[i]]可能会转移到y中求过的状态 造成既下降又上升的情况
FOR(j,down[i]+,up[i]) if(j+y[i-]<up[i-]) {
d[i][j]=min(d[i][j],d[i-][j+y[i-]]);
if(d[i][j]<INF) flag=false;
} if(flag) { //如果本i不能通过那么output退出
int sum=;
FOR(k,,i)
if(up[k]!=m+ || down[k]!=) sum++; //如果是管道 //||而非&&
cout<<<<"\n"<<sum;
return ;
}
} int mini=INF;
FOR(j,,m+) mini=min(mini,d[n][j]); //最右边为n
cout<<<<"\n"<<mini;
return ; }

NOIP2014 飞扬的小鸟的更多相关文章

  1. LOJ2500 NOIP2014 飞扬的小鸟 【背包DP】*

    LOJ2500 NOIP2014 飞扬的小鸟 LINK 题目大意就是说有n个柱子,在每一秒你可以选择不点下降高度y和点p次上升x∗p,若果当前位置加上x∗p大于上界m,就会停在m. 如果可以成功穿越所 ...

  2. [NOIP2014]飞扬的小鸟[DP]

    [NOIP2014]飞扬的小鸟 ——!x^n+y^n=z^n 题目描述: Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画 ...

  3. vijos1907[noip2014]飞扬的小鸟(完全背包)

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

  4. [vijos1907][NOIP2014]飞扬的小鸟

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

  5. NOIP2014飞扬的小鸟

    长为n,高为m的二维平面,其中有k个管道(忽略管道的宽度)小鸟始终在游戏界面内移动.从最左边任意高度位置出发,到达游戏界面最右边,游戏完成每个单位时间沿横坐标方向右移距离为1,竖直移动的距离由玩家控制 ...

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

    坑人啊朴素的dp 75分 用了完全背包才是80分,结果普遍偏小 为什么啊啊啊啊啊 等以后再写一遍吧 #include<iostream> #include<cstdio> #i ...

  7. [NOIP2014]飞扬的小鸟 D1 T3 loj2500 洛谷P1941

    分析: 这是一个DP,没什么好说的,细节很烦人. DP[i][j]表示到第i个位置,高度为j点最少的次数. 转移: 当j=m时 k属于[m-h,m]都可以向DP[i][j]转移,即dp[i][j]=m ...

  8. luogu1941 [NOIp2014]飞扬的小鸟 (dp)

    设f[i][j]为到达(i,j)这个位置的最小操作数 就有$f[i][j]=min\{f[i-1][j+Y[i-1]],f[i-1][j-X[i-1]*k]+k\}$ 然后考虑优化一下转移: 对于一系 ...

  9. [NOIP2014][DP]飞扬的小鸟

    [NOIP2014]飞扬的小鸟 ——!x^n+y^n=z^n 题目描述: Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画 ...

随机推荐

  1. 16进制字符串转数字(C/C++,VB/VB.net,C#)

    这个问题看是很简单,但是在不同语言中实现的方式却千差万别,如果不知道方法,还真是麻烦,我就是在C#中遇到该问题,让我费了很大的周折,才在msdn查到. 一.16进制字符串转数字      1.C/C+ ...

  2. C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法

    学C++的时候,这几个输入函数弄的有点迷糊:这里做个小结,为了自己复习,也希望对后来者能有所帮助,如果有差错的地方还请各位多多指教(本文所有程序均通过VC 6.0运行) 1.cin 2.cin.get ...

  3. [Ruby on Rails系列]4、专题:Rails应用的国际化[i18n]

    1. 什么是internationalization(i18n)? 国际化,英文简称i18n,按照维基百科的定义:国际化是指在设计软件,将软件与特定语言及地区脱钩的过程.当软件被移植到不同的语言及地区 ...

  4. C++不同进制整数

    在C++的整数常量中,整数分为十进制整数.八进制整数和十六进制整数. 那给出一个整型常量怎样区分是何种进制呢?/给出一个整型常量,如100,默认是十进制数,如果在该数前加0,如0100,则此数表示为八 ...

  5. ZooKeeper 安装部署及hello world

    ZooKeeper  安装部署及hello world 先给一堆学习文档,方便以后查看官网文档地址大全: OverView(概述)http://zookeeper.apache.org/doc/r3. ...

  6. 如何用DELPHI编程修改外部EXE文件的版本信

    右击里面有修改 点开直接修改就可以了吧. DELPHI 里程序的版本信息怎么是灰色的,无法更改 耐心读以下说明,应该能解决你的问题,如果不能解决,请Hi我~ 如何给自己的dll文件添加版本信息呢? 首 ...

  7. Eclipse中查看Android模拟器SD卡目录

    · 有时候用到Android模拟器来模拟SD卡相关操作,在Eclipse中可以直接查看SD卡目录: 首先,新建模拟器的时候要创建SD卡,存储的大小根据需要创建: 启动模拟器,在Eclipse中打开视图 ...

  8. 安装 ArcGIS Runtime SDK for Android

    ArcGIS for Android 开发:Android 平台搭建 - liyong20080101的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/liyong ...

  9. yii执行原理

    应用执行流程: 浏览器向服务器发送 Http Request | 控制器(protected/controllers) | |---> Action | 创建模型 (Model) | 检查$_P ...

  10. AC题目简解-dp

    dp类:A - Bridging signals ZOJ 3627 POJ1631 HDU1950给出一个从1-n的数字排列,求最长上升子序列长度.直接说解法吧.新开一个数组d,d[i]表示的是能构成 ...