Description
Flappy Bird 是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败。
为了简化问题,我们对游戏规则进行了简化和改编:
- 游戏界面是一个长为 nn,高为 mm 的二维平面,其中有 kk 个管道(忽略管道的宽度)。
- 小鸟始终在游戏界面内移动。小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成。
- 小鸟每个单位时间沿横坐标方向右移的距离为 11,竖直移动的距离由玩家控制。如果点击屏幕,小鸟就会上升一定高度 XX,每个单位时间可以点击多次,效果叠加;如果不点击屏幕,小鸟就会下降一定高度 YY。小鸟位于横坐标方向不同位置时,上升的高度 XX 和下降的高度 YY 可能互不相同。
- 小鸟高度等于 00 或者小鸟碰到管道时,游戏失败。小鸟高度为 mm 时,无法再上升。
现在,请你判断是否可以完成游戏。如果可以,输出最少点击屏幕数;否则,输出小鸟最多可以通过多少个管道缝隙。
题解
定义 f[i][j] 表示飞到 (i,j) 的最优解,这样,很容易想到暴力转移:枚举前一秒点了几下屏幕。这样的复杂度是 O(n3) 的。考虑优化转移, f[i][j]=min(f[i−1][j−k∗up[i−1]]+k);f[i][j−up[i−1]]=min(f[i−1][j−(k+1)∗up[i−1]]+k) | k=1,2,3...... ,可以发现, f[i][j]=min(f[i−1][j−up[i−1]],f[i][j−up[i−1]])+1 ;稍微注意一下边界就可以了。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10006
#define maxm 1006
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
int n,m,K,ans,U[maxn],D[maxn],up[maxn],dn[maxn],f[maxn][maxm];
int main(){
freopen("bird.in","r",stdin);
freopen("bird.out","w",stdout);
memset(D,0,sizeof(D));memset(U,63,sizeof(U));int INF=U[0];
n=_read();m=_read();K=_read();
for(int i=0;i<n;i++)up[i]=_read(),dn[i]=_read();
for(int i=1,x;i<=K;i++)x=_read(),D[x]=_read(),U[x]=_read();
memset(f,63,sizeof(f));
for(int i=1;i<=m;i++)f[0][i]=0;
for(int i=1;i<=n;i++){
for(int j=up[i-1];j<=m;j++)f[i][j]=min(f[i][j-up[i-1]],f[i-1][j-up[i-1]])+1;
for(int j=m-up[i-1];j<=m;j++)f[i][m]=min(f[i][m],min(f[i][j],f[i-1][j])+1);
for(int j=1;j<=m-dn[i-1];j++)f[i][j]=min(f[i][j],f[i-1][j+dn[i-1]]);
for(int j=1;j<=m;j++) if(j<=D[i]||j>=U[i])f[i][j]=INF;
}
ans=INF;
for(int i=1;i<=m;i++)ans=min(ans,f[n][i]);
if(ans==INF){
printf("0\n");
ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)if(f[i][j]<INF){ans=i;break;}
int ans0=0;
for(int i=1;i<=ans;i++) if(U[i]<INF)ans0++;
printf("%d\n",ans0);
}else printf("1\n%d\n",ans);
return 0;
}