刷过一题之NOIP2012寻宝

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷过一题之NOIP2012寻宝相关的知识,希望对你有一定的参考价值。

    传说很遥远的藏宝楼顶层藏着诱人的宝藏。 小明历尽千辛万苦终于找到传说中的这个藏宝楼,藏宝楼的门口竖着一个木板,上面写有几个大字:寻宝说明书。
    说明书的内容如下:藏宝楼共有N+1层,最上面一层是顶层,顶层有一个房间里面藏着宝藏。除了顶层外,藏宝楼另有 N层,每层M个房间,这M个房间围成一圈并按逆时针方向依次编号为0,…,M-1。其中一些房间有通往上一层的楼梯,每层楼的楼梯设计可能不同。每个房间里有一个指示牌,指示牌上有一个数字x,表示从这个房间开始按逆时针方向选择第x个有楼梯的房间(假定该房间的编号为k),从该房间上楼,上楼后到达上一层的k号房间。比如当前房间的指示牌上写着2,则按逆时针方向开始尝试,找到第2个有楼梯的房间,从该房间上楼。如果当前房间本身就有楼梯通向上层,该房间作为第一个有楼梯的房间。寻宝说明书的最后用红色大号字体写着:“寻宝须知:帮助你找到每层上楼房间的指示牌上的数字(即每层第一个进入的房间内指示牌上的数字)总和为打开宝箱的密钥”。请帮助小明算出这个打开宝箱的密钥。

 

输入:

第一行2个整数N和M,之间用一个空格隔开。N表示除了顶层外藏宝楼共N层楼,M表示除顶层外每层楼有M个房间。接下来N*M行,每行两个整数,之间用一个空格隔开,每行描述一个房间内的情况,其中第(i-1)*M+j 行表示第i层j-1号房间的情况(i=1,2,…,N;j=1,2,…,M)。第一个整数表示该房间是否有楼梯通往上一层(0表示没有,1表示有),第二个整数表示指示牌上的数字。注意,从j号房间的楼梯爬到上一层到达的房间一定也是j号房间。最后一行,一个整数,表示小明从藏宝楼底层的几号房间进入开始寻宝(注:房间编号从0开始)。

 

输出:

输出只有一行,一个整数,表示打开宝箱的密钥,这个数可能会很大,请输出对20123取模的结果即可。

 

输入示例:
2 3
1 2
0 3
1 4
0 1
1 5
1 2
1
 
输出示例:
5
 
【输入输出样例说明】
    第一层:
        0 号房间,有楼梯通往上层,指示牌上的数字是 2; 
        1 号房间,无楼梯通往上层,指示牌上的数字是 3;
        2 号房间,有楼梯通往上层,指示牌上的数字是 4;
    第二层:
        0 号房间,无楼梯通往上层,指示牌上的数字是 1;
        1 号房间,有楼梯通往上层,指示牌上的数字是 5;
        2 号房间,有楼梯通往上层,指示牌上的数字是 2;
小明首先进入第一层(底层)的 1 号房间,记下指示牌上的数字为3,然后从这个房间开始, 沿逆时针方向选择第3个有楼梯的房间2号房间进入,上楼后到达第二层的2号房间,记下指示牌上的数字为2, 由于当前房间本身有楼梯通向上层,该房间作为第一个有楼梯的房间。因此,此时沿逆时针方向选择第2个有楼梯的房间即为1号房间,进入后上楼梯到达顶层。这时把上述记下的指示牌上的数字加起来,即3+2=5,所以打开宝箱的密钥就是5。
【数据范围】0<N≤10000,0<M≤100,0<x≤1,000,000。
 

其实这题就是模拟。但是纯粹模拟会时间超限,所以要在上楼处取模以优化。

技术分享
 1 #include<iostream>
 2 using namespace std;
 3 int ans,n,begin,m,s[10000],map[10000][100],floor[10000][100];
 4 int read()
 5 {
 6     int x=0,f=1;
 7     char ch=getchar();
 8     while(ch<0||ch>9)
 9     {
10         if(ch==-) f=-1;
11         ch=getchar();
12     }
13     while(ch>=0&&ch<=9)
14     {
15         x=x*10+ch-0;
16         ch=getchar();
17     }
18     return x*f;
19 }
20 int main()
21 {
22     n=read();
23     m=read();
24     for(int i=0;i<n;i++)
25         for(int j=0;j<m;j++) 
26         {
27             map[i][j]=read(),floor[i][j]=read();//输入 
28             if(map[i][j]==1) s[i]++;//记录每行有几个有楼梯的房间 
29         }
30     begin=read();
31     for(int i=0;i<n;i++)
32     {
33         ans+=floor[i][begin];//累加上楼梯房间牌子上的数字之和 
34         ans%=20123;//对答案取模 
35         if(i==n-1) break;
36         if(floor[i][begin]%s[i]!=0) floor[i][begin]%=s[i];//记录上楼梯房间 
37         if(floor[i][begin]%s[i]==0) floor[i][begin]=s[i];//记录上楼梯房间
38         int k=floor[i][begin];//用k暂存begin的初始值 
39         if(map[i][begin]==1) k--;//找到一个带楼梯房间 
40         while(k>0)
41         {
42             begin++;
43             if(begin==m) begin=0;//如果找到头,从头再找 
44             if(map[i][begin]==1) k--;//找到一个带楼梯房间 
45         }
46     }
47     printf("%d",ans%20123);//对答案取模 
48     //system("pause>nul");
49     return 0;
50 }
C++ answer

 

以上是关于刷过一题之NOIP2012寻宝的主要内容,如果未能解决你的问题,请参考以下文章

刷过一题之NOIP2013转圈游戏

刷过一题之NOIP2013表达式求值

刷过一题之NOIP2007守望者的逃离

刷过一题之区间最小值

刷过一题之矩阵最小值

寻宝(NOIP2012普及组第二题)