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;
}

 

posted @ 2024-05-31 08:54  五月江城  阅读(257)  评论(0编辑  收藏  举报