洛谷 NOIP2012 普及组 寻宝

先看题目:

输入输出格式与数据范围:

 

 可能这道题目有点绕,先给读者解读下题意:

以测试样例为例,就是首先n,m分别代表了楼层数和每一层楼的房间数目,然后样例n,m分别不是2、3嘛,然后接下来输入的每三行就代表了一层楼的每个房间,每一行两个数字,第一个数字为0 1表示该房间是否存在楼梯通往下一层楼,第二个数字就是代表了房间里面指示牌的数字。

然后最下面那一行一个数字代表了一开始从最底层的哪一个房间号开始探险。

接下来我阐述一下我的个人思路:

首先利用两个二维数组,第一个二维数组stair表示每一层的每个房间是否有能通往上一层的楼梯,第二个二维数组代表每一层的每个房间指示牌上面的数字,话不多说,先上我一开始不能得到满分的代码:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int stair[11000][110],num[11000][110];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=0;j<m;j++)
		scanf("%d%d",&stair[i][j],&num[i][j]);
	}
	int pos;
	scanf("%d",&pos);
	int ans;
	for(int i=1;i<=n;i++){
		int x=num[i][pos];
		ans=(ans+x)%20123;
		if(stair[i][pos]) --x;
		while(x){
			pos=(pos+1)%m;
			if(stair[i][pos]) --x;
		}
	}
	printf("%d\n",ans);
	return 0;
}

很遗憾的是只有五十分,我们来分析一下为什么,观察一下测试的案例,对于百分之五十的数据,N,x的值并不大,然而对于百分之一百的数据,x的最大值来到了一百万,这就意味着最大的循环次数达到了n*x上亿的原子操作数,也就意味着时间复杂度过大了,那么我们就需要想办法优化一下时间复杂度,仔细观察,对于每一层的房间个数最大也就是100,然而x的最大值和房间个数差距也太大了,所以我们不妨考虑对x取模,x的值换成每层楼里面有楼梯通往下一层的房间的个数,这样,循环次数就会大大减小,那么接下来看一下我修改之后的代码:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int stair[10010][110],num[10010][110];
int ans,pos;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=0;j<m;j++){
			scanf("%d%d",&stair[i][j],&num[i][j]);
		}
	}
	scanf("%d",&pos);
	for(int i=1;i<=n;i++){
		int x=num[i][pos];
		ans=(ans+x)%20123;
		int t=0;
		for(int j=0;j<m;j++)
		t+=stair[i][j];
		x%=t;
		if(x==0) x=t;
		if(stair[i][pos]) x--;
		while(x){
			pos=(pos+1)%m;
			if(stair[i][pos]) --x;
		}
	}
	printf("%d\n",ans);
	return 0;
}

这样就完成了时间复杂度的优化,是能获得满分的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

残念亦需沉淀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值