Flappy Kotori是很好玩的游戏
对于这道题目,我的第一感觉是动态规划,但不知道应该如何实现。但实际上还是能想到的,只是要注意许多细节。
我们定义二维数组dp[i][j]代表到第i列第j个位置(如原题图)需要至少多少步。记录下每一列上升下降的格数up[i],down[i]。并初始化每一列能走的上限high[i]=0,下限low[i]=m+1。读入有油管的情况,将该列的上限和下限数组更新,并记录当前列有油管(便于最后无法通过的情况记录通过的油管数时使用)。初始化dp数组为INF,并初始化第0列所有行是0(一开始从第0列任意点出发)。然后我们可以从第0列到第n-1列开始,首先更新dp数组跳一下的情况(01背包),注意要判断在跳一下后如果没到天花板最高高度就是当前的+该列向上跳的高度,如果到了天花板最高高度只能是m。然后我们需要处理在单位时间内连续跳的情况(完全背包),我们这里枚举高度j 从1到m,并不断更新我们求出跳一次的值。这里可能不太好理解,举个例子,第一次跳小鸟从1跳到3,然后我们j变为2就是从2到4,然后变为3就是从3到5,这时我们可以把它看做从第一次的1跳两次到了5,。最后我们处理下落的情况,注意下落时的最低高度应该是max(最低油管的顶部+1,当前列下落距离+1),不然鸟就摔死了。然后dp更新即可,这里就不需要加步数了。初始化最小值minn为INF,最后我们对第n列的每一行dp值找最小值,如果不是INF,就输出1与minn。如果没有最小值说明飞不到那里。这时我们需要从n-1列到第1列寻找该列里能到达的每一行dp值的最小值,首先判断该行有没有油管,在这个判断前提下如果是INF说明鸟飞不到那里,所以k值减1。若不是INF就飞到那里停止了,输出0与k即可。最后注意可能有不经过任何油管但飞不到的情况,应该在这个循环外输出0,0。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=10010;
const int maxm=1010;
int dp[maxn][maxm];
int up[maxn],down[maxn],low[maxn],high[maxn];
int n,m,k;
bool b[maxn];
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++)
{
scanf("%d%d",&up[i],&down[i]);
}
for(int i=0;i<=n;i++)
{
low[i]=0;
high[i]=m+1;
}
for(int i=1;i<=k;i++)
{
int t;
scanf("%d",&t);
scanf("%d %d",&low[t],&high[t]);
b[t]=true;
}
memset(dp,INF,sizeof(dp));
for(int i=1;i<=m;i++) dp[0][i]=0;
for(int i=0;i<n;i++)
{
for(int j=low[i]+1;j<high[i];j++)
{
if(j+up[i]<=m) dp[i+1][j+up[i]]=min(dp[i+1][j+up[i]],dp[i][j]+1);
else dp[i+1][m]=min(dp[i+1][m],dp[i][j]+1);
}
for(int j=1;j<=m;j++)
{
if(j+up[i]<=m) dp[i+1][j+up[i]]=min(dp[i+1][j+up[i]],dp[i+1][j]+1);
else dp[i+1][m]=min(dp[i+1][m],dp[i+1][j]+1);
}
for(int j=max(low[i]+1,down[i]+1);j<high[i];j++)
{
dp[i+1][j-down[i]]=min(dp[i+1][j-down[i]],dp[i][j]);
}
}
int minn=INF;
for(int i=1;i<=m;i++)
{
//cout<<dp[n][i]<<endl;
minn=min(minn,dp[n][i]);
}
if(minn!=INF)
{
cout<<"1"<<endl<<minn<<endl;
return 0;
}
for(int i=n-1;i>0;i--)
{
if(b[i])
{
int minn=INF;
for(int j=low[i]+1;j<=high[i]-1;j++)
{
minn=min(minn,dp[i][j]);
}
if(minn!=INF)
{
cout<<"0"<<endl<<k<<endl;
return 0;
}
k--;
}
}
cout<<"0"<<endl<<"0"<<endl;
return 0;
}