笨笨鸟

笨笨鸟

题目描述

       GM下载了一款流行手机游戏“笨笨鸟”,主角笨笨鸟在一个10行N列的方格中移动,一开始笨笨鸟在左下角的方格中心,作为起点准备出发,若GM不做任何操作,笨笨鸟将一直向右以1秒1格的速度移动,若按下手机屏幕,笨笨鸟将起飞,以右上45度飞翔,一旦按下手机屏幕的手指松开,笨笨鸟将以右下45度滑翔。值得注意的是,到了顶行依然按下不松手,笨笨鸟将向右1秒1格移动,GM不怎么会玩游戏,请帮助他让笨笨鸟成为不死鸟(即不触碰障碍物顺利通过N列)。

输入格式

       第一行输入包含整数N(1≤N≤1e5 )。表示场地有多少列。

      接下来10行中的每一行包含N个字符。字符是. 或者X ,表示游戏中场地的布局,字符X表示障碍物, . 表示可以走的地方。所有输入数据保证有解。

输出格式

       第一行输出必须包含整数P(0≤P≤5∗1e4 )。表示GM按下按钮的次数 。

       接下来 P行,每行输出一次操作,以达到通关游戏的目的。

       每次操作由两个整数ti​和xi决定,其中ti表示本次操作按下按钮的开始时间,xi表示本次操作按下按钮的持续时间。

       所有操作必须按时间顺序进行排序。换句话说ti​+xi​≤ti+1​。此外,在游戏结束后不应该有操作开始,即ti​<N。

       如果存在多个解决方案,则输出任意一个。本题答案已经写了SPJ。

       分数分布:无特殊分数分布。

样例输入

20

X..................X

.X................X.

..X..............X..

...X............X...

....X..........X....

.....X........X.....

......X......X......

.......X....X.......

........X..X........

.........XX.........

 样例输出

1

8 10

 本题是一道模拟加dp的题,用dp[i,j]来表示是否可以到达[i,j]这个格子,顺便记录下上一个节点的状况

dp[i][j] dp[i+1][j-1]|dp[i][j-1]  (i==0)

           dp[i+1][j-1]|dp[i-1][j-1]  (0<i<9)

           dp[i-1][j-1]|dp[i][j-1]  (i==9)

把整个图遍历一遍就行了

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
int n;bool pr[100005];
int tot,begn[50005],last[50005];
char maze[15][100005];
bool dp[15][100005];int pre[15][100005];
void read(int &x)
{
	int f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}//读入优化
void print(int sx,int sy)
{
	//printf("%d %d\n",sx,sy);
	if(sy<=0) return ;
	print(pre[sx][sy],sy-1);
	if(sx==pre[sx][sy]+1||(sx==9&&pre[sx][sy]==9)) pr[sy]=0;
	if(sx==pre[sx][sy]-1||(sx==0&&pre[sx][sy]==0)) pr[sy]=1;
	if(pr[sy]&&!pr[sy-1])
		tot++,last[tot]=0,begn[tot]=sy;
	if(pr[sy]) last[tot]++;
}//更新出按键的时间
int main()
{
	//freopen("Jetpack.in","r",stdin);
	//freopen("Jetpack.out","w",stdout);
	scanf("%d",&n);
	for(int i=0;i<10;i++)
	{
		scanf("\n");
		for(int j=0;j<n;j++)
			scanf("%c",&maze[i][j]);
	}//输入图
	dp[9][0]=1;
	for(int j=1;j<n;j++)
		for(int i=9;i>=0;i--)
		{
			if(maze[i][j]=='X') continue;
			if(i==9)
				if(dp[i][j-1])
					dp[i][j]=1,pre[i][j]=i;//特判(i==9)的情况
			if(i==0)
				if(dp[i][j-1])
					dp[i][j]=1,pre[i][j]=i;//特判(i==0)的情况
			if(i>0)
				if(dp[i-1][j-1])
					dp[i][j]=1,pre[i][j]=i-1;//按键
			if(i<9)
				if(dp[i+1][j-1])
					dp[i][j]=1,pre[i][j]=i+1;//不按
		}//加载出整个图,是否可以到达
	for(int i=0;i<10;i++)
		if(dp[i][n-1])//随便找个答案输出
		{
			print(i,n-1);
			printf("%d\n",tot);
			for(int j=1;j<=tot;j++)
				printf("%d %d\n",begn[j],last[j]);
			return 0;
		}
	return 0;
}

谢谢阅读!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值