CSP历年复赛题-P1076 [NOIP2012 普及组] 寻宝
原题链接:https://www.luogu.com.cn/problem/P1076
题意解读:n+1层楼,每层楼m个房间,编号0~m-1成环状,每个房间有一个指示牌数字(表示逆时针遇到第几个有楼梯的房间后上楼),有的有向上的楼梯,给定一个底层的起始房间,计算到首次到每一层(1~n层)的房间指示牌数字之和。
解题思路:
每层楼一个环形数组代表房间,因此用二维数组即可表示,为便于处理,数组下标都从0开始。
此题关键在于上到每一层,要根据指示牌数字找到第x个有楼梯的房间,如果直接枚举,x最大为10^6,楼层为10^5,将超时!
又因为每层楼房间不超过100,因此可以将每层楼有楼梯的房间数提前统计出来,用x % 当前楼层有楼梯的房间数,对余数再进行枚举,就能大大缩减枚举时间。
这里要注意的点是,如果x % 房间数s[i] = 0,则要找到第s[i]个有楼梯的房间,不能是第0个。
最后,注意结果要对20123取模。
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 10005, M = 105, MOD = 20123;
int n, m, start;
int v[N][M]; //v[i][j]表示i层,j号房间是否有通往上层的楼梯
int w[N][M]; //w[i][j]表示i层,j号房间指示牌的数字
int s[N]; //s[i]表示第i层一共有多少个楼梯
int ans;
int main()
{
cin >> n >> m;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
cin >> v[i][j] >> w[i][j];
s[i] += v[i][j];
}
}
cin >> start;
ans += w[0][start];
for(int i = 0; i < n - 1; i++) //寻找每一层上楼的房间,第n层不用找
{
int x = w[i][start]; //当前楼层起始房间的指示牌数字
int r = x % s[i]; //找第r个有楼梯的房间即可,缩短查找时间
if(r == 0) r = s[i]; //关键句,如果正好s[i]倍,要找第s[i]个,不能是0个
int cnt = 0;
while(true)
{
if(v[i][start] == 1)
{
if(++cnt == r) break;
}
start = (start + 1) % m;
}
ans += w[i+1][start];
ans %= MOD;
}
cout << ans;
return 0;
}