前两天刚刚做完2014年noipD1T3飞扬的小鸟

其实这道题本身并不是一道很难的DP

状态容易想到,转移也容易想到

但是出于我的基础较差,还是出了较大的偏差

Problem:

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

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

  1. 游戏界面是一个长为n ,高为 m 的二维平面,其中有k 个管道(忽略管道的宽度)。

  2. 小鸟始终在游戏界面内移动。小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成。

  3. 小鸟每个单位时间沿横坐标方向右移的距离为1 ,竖直移动的距离由玩家控制。如果点击屏幕,小鸟就会上升一定高度X ,每个单位时间可以点击多次,效果叠加;

如果不点击屏幕,小鸟就会下降一定高度Y 。小鸟位于横坐标方向不同位置时,上升的高度X 和下降的高度Y 可能互不相同。

  1. 小鸟高度等于0 或者小鸟碰到管道时,游戏失败。小鸟高度为 m 时,无法再上升。

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

输入输出格式

输入格式:

第1 行有3 个整数n ,m ,k ,分别表示游戏界面的长度,高度和水管的数量,每两个

整数之间用一个空格隔开;

接下来的n 行,每行2 个用一个空格隔开的整数X 和Y ,依次表示在横坐标位置0 ~n- 1

上玩家点击屏幕后,小鸟在下一位置上升的高度X ,以及在这个位置上玩家不点击屏幕时,

小鸟在下一位置下降的高度Y 。

接下来k 行,每行3 个整数P ,L ,H ,每两个整数之间用一个空格隔开。每行表示一

个管道,其中P 表示管道的横坐标,L 表示此管道缝隙的下边沿高度为L ,H 表示管道缝隙

上边沿的高度(输入数据保证P 各不相同,但不保证按照大小顺序给出)。

输出格式:

共两行。

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

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

输入输出样例

输入样例#1:

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:

1
6
输入样例#2:

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
输出样例#2:

0
3

说明

【输入输出样例说明】

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

【数据范围】

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

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

对于70% 的数据:5 ≤ n ≤ 1000,5 ≤ m ≤ 1 0 0 ;

对于100%的数据:5 ≤ n ≤ 100 0 0 ,5 ≤ m ≤ 1 0 00,0 ≤ k < n ,0<X < m ,0<Y <m,0<P <n,0 ≤ L < H ≤ m ,L +1< H 。

Solution:

一开始读完题目,就非常迅速的想到了DP,于是上手就开始打了,

粗粗的列了列式子,并没有算复杂度,于是一开始复杂度接近 O(n*m*m)

第一遍打完,调过了样例,又测了几组发现都非常正确,于是果断交

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
int up[N],dw[N],sum[N],d[N],u[N],f[N][];
int n,m,k,x,y,z;
int main(){
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<=n;++i) scanf("%d%d",&up[i],&dw[i]);
for (int i=;i<=k;++i)
scanf("%d%d%d",&x,&y,&z),u[x]=y,d[x]=z;
for (int i=;i<=n;++i) sum[i]=sum[i-]+(d[i]>);
for (int i=;i<=n;++i) for (int j=;j<=m;++j) f[i][j]=1e9;
for (int i=;i<=m;++i) f[][i]=;
for (int i=;i<=n;++i)
for (int j=;j<=m;++j) if (f[i-][j]<1e9){
if (j>dw[i])
if (u[i]||d[i]){
if (j-dw[i]>u[i]&&j-dw[i]<d[i]) f[i][j-dw[i]]=min(f[i][j-dw[i]],f[i-][j]);
} else f[i][j-dw[i]]=min(f[i][j-dw[i]],f[i-][j]); int lim=(m-j)/up[i];
if ((m-j)%up[i]==) lim++;
for (int k=;k<=lim;++k){
int he=j+k*up[i]; if (he>m) he=m;
if (u[i]||d[i]){
if (he>u[i]&&he<d[i]) f[i][he]=min(f[i][he],f[i-][j]+k);
} else f[i][he]=min(f[i][he],f[i-][j]+k);
}
}
int ans=1e9;
// for (int i=1;i<=n;++i)
// for (int j=1;j<=m;++j) if (f[i][j]!=1e9) printf("f[%d][%d]=%d\n",i,j,f[i][j]);
for (int i=;i<=m;++i)
ans=min(ans,f[n][i]);
if (ans<1e9) printf("1\n%d",ans); else
for (int i=;i<=n;++i){
bool flag=;
for (int j=;j<=m;++j)
if (f[i][j]<1e9){flag=; break;}
if (flag){printf("0\n%d",sum[i-]); return ;}
} }

结果发现题意理解不够清楚,因为它在m高度的时候也可以继续跳,只是高度不变,于是改了一发再交

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
int up[N],dw[N],sum[N],d[N],u[N],f[N][];
int n,m,k,x,y,z;
int main(){
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<=n;++i) scanf("%d%d",&up[i],&dw[i]);
for (int i=;i<=k;++i)
scanf("%d%d%d",&x,&y,&z),u[x]=y,d[x]=z;
for (int i=;i<=n;++i) sum[i]=sum[i-]+(d[i]>);
for (int i=;i<=n;++i) for (int j=;j<=m;++j) f[i][j]=1e9;
for (int i=;i<=m;++i) f[][i]=;
for (int i=;i<=n;++i)
for (int j=;j<=m;++j) if (f[i-][j]<1e9){
if (j>dw[i])
if (u[i]||d[i]){
if (j-dw[i]>u[i]&&j-dw[i]<d[i]) f[i][j-dw[i]]=min(f[i][j-dw[i]],f[i-][j]);
} else f[i][j-dw[i]]=min(f[i][j-dw[i]],f[i-][j]); int lim=(m-j)/up[i];
if ((m-j)%up[i]!=||(m-j==)) lim++;
for (int k=;k<=lim;++k){
int he=j+k*up[i]; if (he>m) he=m;
if (u[i]||d[i]){
if (he>u[i]&&he<d[i]) f[i][he]=min(f[i][he],f[i-][j]+k);
} else f[i][he]=min(f[i][he],f[i-][j]+k);
}
}
int ans=1e9;
// for (int i=1;i<=n;++i)
// for (int j=1;j<=m;++j) if (f[i][j]!=1e9) printf("f[%d][%d]=%d\n",i,j,f[i][j]);
for (int i=;i<=m;++i)
ans=min(ans,f[n][i]);
if (ans<1e9) printf("1\n%d",ans); else
for (int i=;i<=n;++i){
bool flag=;
for (int j=;j<=m;++j)
if (f[i][j]<1e9){flag=; break;}
if (flag){printf("0\n%d",sum[i-]); return ;}
} }

T75 现在突然意识到自己的DP复杂度根本不对

贴了快读,加了register,再交

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=;
int up[N],dw[N],sum[N],d[N],u[N],f[N][];
int n,m,k,x,y,z;
template<class T>
inline void read(T &x) {
bool Finish_read=;x=;int f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;if(ch==EOF) return;ch=getchar();}
while(isdigit(ch))x=x*+ch-'',ch=getchar();
x*=f;Finish_read=;
}
template<class T>
inline void print(T x) {
if(x/!=) print(x/);
putchar(x%+'');
}
template<class T>
inline void writeln(T x) {
if(x<) putchar('-');
print(x); putchar('\n');
}
inline int min(int x,int y){return x<y?x:y;}
int main(){
read(n); read(m); read(k);
for (register int i=;i<=n;++i) read(up[i]),read(dw[i]);
for (register short i=;i<=k;++i)
read(x),read(y),read(z),u[x]=y,d[x]=z;
for (register int i=;i<=n;++i) sum[i]=sum[i-]+(d[i]>);
for (register int i=;i<=n;++i) for (short j=;j<=m;++j) f[i][j]=1e9;
for (register short i=;i<=m;++i) f[][i]=;
for (register int i=;i<=n;++i)
for (register short j=;j<=m;++j) if (f[i-][j]<1e9){
if (j>dw[i])
if (d[i]>){
if (j-dw[i]>u[i]&&j-dw[i]<d[i]) f[i][j-dw[i]]=min(f[i][j-dw[i]],f[i-][j]);
} else f[i][j-dw[i]]=min(f[i][j-dw[i]],f[i-][j]); int lim=(m-j)/up[i];
if ((m-j)%up[i]!=||(m-j==)) lim++;
for (register short k=;k<=lim;++k){
int he=j+k*up[i]; if (he>m) he=m;
if (d[i]>){
if (he>u[i]&&he<d[i]) f[i][he]=min(f[i][he],f[i-][j]+k);
} else f[i][he]=min(f[i][he],f[i-][j]+k);
}
}
int ans=1e9;
for (register short i=;i<=m;++i)
ans=min(ans,f[n][i]);
if (ans<1e9) printf("1\n%d",ans); else
for (register int i=;i<=n;++i){
bool flag=;
for (register short j=;j<=m;++j)
if (f[i][j]<1e9){flag=; break;}
if (flag){printf("0\n%d",sum[i-]); return ;}
} }

好像多了5分,但并没什么用

到了晚上,在想这道题,大力加了一发剪枝,剪掉了一些不必要DP的情况

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const short N=;
int up[N],dw[N],sum[N],d[N],u[N],f[N][];
int n,m,k,x,y,z,ans=;
template<class T>
inline void read(T &x) {
bool Finish_read=;x=;int f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;if(ch==EOF) return;ch=getchar();}
while(isdigit(ch))x=x*+ch-'',ch=getchar();
x*=f;Finish_read=;
}
template<class T>
inline void print(T x) {
if(x/!=) print(x/);
putchar(x%+'');
}
template<class T>
inline void writeln(T x) {
if(x<) putchar('-');
print(x); putchar('\n');
}
inline int min(int x,int y){return x<y?x:y;}
bool check(int x){
for(int i=u[x]+;i<=d[x]-;i++)
if (f[x][i]<1e9) return ;
return ;
}
int main(){
read(n); read(m); read(k);
for (register int i=;i<=n;++i) read(up[i]),read(dw[i]);
for (register short i=;i<=k;++i)
read(x),read(y),read(z),
u[x]=y,d[x]=z;
for (register int i=;i<=n;++i)
sum[i]=sum[i-]+(d[i]>);
for (register short i=;i<=n;++i)
for (short j=;j<=m;++j) f[i][j]=1e9;
for (register short i=;i<=m;++i) f[][i]=; //
for (register int i=;i<=n;++i){
short l=,r=m;
if (d[i-]>)
l=u[i-]+,r=d[i-]-,ans++;
for (register short j=r;j>=l;--j) if (f[i-][j]<1e9){
if (j>dw[i])
f[i][j-dw[i]]=min(f[i][j-dw[i]],f[i-][j]);
for (register short k=;k<=m/up[i]+;++k){
int he=j+k*up[i];
if (d[i]>){
if (he>=d[i]) break;
if (he<=u[i]) continue;
}
if (he<m){
if (f[i-][j]+k>f[i][he]) break;
f[i][he]=f[i-][j]+k;
} else {
f[i][m]=min(f[i-][j]+k,f[i][m]); break;
}
}
}
if (d[i]&&!check(i)) break;
}
if (ans<k){
printf("0\n%d",ans); return ;
}
int l=,r=m; ans=1e9;
if (d[n]>) l=u[n]+,r=d[n]-;
for (int i=l;i<=r;++i) ans=min(ans,f[n][i]);
printf("1\n%d",ans);
return ;
}

然后就跑的飞快了QAQ

当然以上的过程我已经将他简化,事实上我还交了很多很多发(本人比较菜没办法)

Summary:

(1)比赛时候做题,不要慌张,看完题目不要马上上手,仔细读完所有题目给定的条件

(2)如遇到这种DP题,要清楚的算清复杂度,如会T,需要大力加剪枝,或重新思考

(3)积极打暴力,如有时间一定要对拍

从flappy bird中论优化的更多相关文章

  1. canvas 制作flappy bird(像素小鸟)全流程

    flappy bird制作全流程: 一.前言 像素小鸟这个简单的游戏于2014年在网络上爆红,游戏上线一段时间内appleStore上的下载量一度达到5000万次,风靡一时, 近年来移动web的普及为 ...

  2. C语言版flappy bird黑白框游戏

    在此记录下本人在大一暑假,2014.6~8这段时间复习C语言,随手编的一个模仿之前很火热的小游戏----flappy bird.代码bug基本被我找光了,如果有哪位兄弟找到其他的就帮我留言下吧,谢谢了 ...

  3. [MFC] 高仿Flappy bird 桌面版

    这是今年年初做的东西,一直没有时间整理,现在拿出来分享下~ 目录 开发背景 开发语言及运行环境 效果展示 游戏框架说明 游戏状态及逻辑说明 经典算法说明 重量级问题解决 开发感想 一.开发背景: fl ...

  4. 程序员带你一步步分析AI如何玩Flappy Bird

    以下内容来源于一次部门内部的分享,主要针对AI初学者,介绍包括CNN.Deep Q Network以及TensorFlow平台等内容.由于笔者并非深度学习算法研究者,因此以下更多从应用的角度对整个系统 ...

  5. 自己动手写游戏:Flappy Bird

    START:最近闲来无事,看了看一下<C#开发Flappy Bird游戏>的教程,自己也试着做了一下,实现了一个超级简单版(十分简陋)的Flappy Bird,使用的语言是C#,技术采用了 ...

  6. 闲扯游戏编程之html5篇--山寨版《flappy bird》源码

    新年新气象,最近事情不多,继续闲暇学习记点随笔,欢迎拍砖.之前的〈简单游戏学编程语言python篇〉写的比较幼稚和粗糙,且告一段落.开启新的一篇关于javascript+html5的从零开始的学习.仍 ...

  7. 【Unity3D基础教程】给初学者看的Unity教程(四):通过制作Flappy Bird了解Native 2D中的RigidBody2D和Collider2D

    作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 引子 在第一篇文章[Unity3D基础教程] ...

  8. 65行 JavaScript 代码实现 Flappy Bird 游戏

    飞扬的小鸟(Flappy Bird)无疑是2014年全世界最受关注的一款游戏.这款游戏是一位来自越南河内的独立游戏开发者阮哈东开发,形式简易但难度极高的休闲游戏,很容易让人上瘾. 这里给大家分享一篇这 ...

  9. 用Phaser来制作一个html5游戏——flappy bird (二)

    在上一篇教程中我们完成了boot.preload.menu这三个state的制作,下面我们就要进入本游戏最核心的一个state的制作了.play这个state的代码比较多,我不会一一进行说明,只会把一 ...

随机推荐

  1. stall and flow separation on airfoil or blade

    stall stall and flow separation Table of Contents 1. Stall and flow separation 1.1. Separation of Bo ...

  2. python正则表达式的好文章(转)

    http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html https://blog.csdn.net/shw800/article/det ...

  3. 洛谷 1097 统计数字(NOIp2007提高组T1)

    [题解] 排个序然后扫一遍进行统计即可. #include<cstdio> #include<algorithm> #include<cstring> #defin ...

  4. 洛谷 1712 BZOJ 4653 [NOI2016]区间

    [题解] 先把区间按照未离散化的长度排序,保存区间长度,然后离散化区间端点.每次把区间覆盖的点的覆盖次数加1,如果某个点被覆盖次数大于等于m,就从前往后开始删除区间直到没有一个点被覆盖的次数大于等于m ...

  5. Maven_自动化构建和构建环节

    [构建过程的几个主要环节] ①清理:删除以前的编译结果,为重新编译做好准备. ②编译:将 Java 源程序编译为字节码文件. ③测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性 ...

  6. vue.js组件之间的通讯-----父亲向儿子传递数据,儿子接收父亲的数据

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 你的ExcelUtil简单、高效、易扩展吗

    你的ExcelUtil简单.高效.易扩展吗 Author: Dorae Date: 2018年10月23日12:30:15 转载请注明出处 一.背景 最近接到了和Excel导出相关的需求,但是: 项目 ...

  8. 强连通图 HDU - 1269

    为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以 ...

  9. R - Milking Time DP

    Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that sh ...

  10. 配置类Configuration怎样使用

    public class CorsConfiguration { /** * Wildcard representing <em>all</em> origins, metho ...