1. 程式人生 > >2012NOIP普級組第二題--尋寶(參考洛谷題解)

2012NOIP普級組第二題--尋寶(參考洛谷題解)

一、題目描述

傳說很遙遠的藏寶樓頂層藏著誘人的寶藏。小明歷盡千辛萬苦終於找到傳說中的這個藏寶樓,藏寶樓的門口豎著一個木板,上面寫有幾個大字:尋寶說明書。說明書的內容如下:

藏寶樓共有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取模的結果即可。

輸入輸出樣例

輸入樣例#1: 複製
2 3
1 2
0 3
1 4
0 1
1 5
1 2
1
輸出樣例#1: 複製
5

說明

【資料範圍】

對於50%資料,有0<N≤1000,0<x≤10000;

對於100%資料,有0<N≤10000,0<M≤100,0<x≤1,000,000。

NOIP 2012 普及組 第二題

二、解題思路

  樣例解讀:

第一層:

0 號房間,有樓梯通往上層,指示牌上的數字是 2;

1 號房間,無樓梯通往上層,指示牌上的數字是 3;

2 號房間,有樓梯通往上層,指示牌上的數字是 4;

第二層:

0 號房間,無樓梯通往上層,指示牌上的數字是 1;

1 號房間,有樓梯通往上層,指示牌上的數字是 5;

2 號房間,有樓梯通往上層,指示牌上的數字是 2;

小明首先進入第一層(底層)的 1 號房間,記下指示牌上的數字為3,然後從這個房間開始, 沿逆時針方向選擇第3個有樓梯的房間2號房間進入,上樓後到達第二層的2號房間,記下指示牌上的數字為2, 由於當前房間本身有樓梯通向上層,該房間作為第一個有樓梯的房間。因此,此時沿逆時針方向選擇第2個有樓梯的房間即為1號房間,進入後上樓梯到達頂層。這時把上述記下的指示牌上的數字加起來,即3+2=5,所以開啟寶箱的金鑰就是5。

解題注意點:

1.走的步數要對當前這層有樓梯的房間數量%,不然會tle s=f[i][now]%w[i];

2.%後可能為0,則應該就為當前有樓梯房間數量 if (s==0) s=w[i];

3.房間從0號開始標號不是一號

三、參考程式碼

#include<iostream>

using namespace std;

struct room{int flag,num;};  //flag:有沒有樓梯

int main()

{

    int n,m,first,i,j,key=0;  //key:鑰匙

    room rooms[10001][101];  //儲存房間

    int room_num[101],stair_tot;  //走著瞧,呵~~~

    cin>>n>>m;

    for(i=1;i<=n;i++)

    for(j=0;j<m;j++)

    cin>>rooms[i][j].flag>>rooms[i][j].num;  //輸入

    cin>>first;

    i=1; while(i<=n)  //一層一層往上走

    {

        stair_tot=0;  //該樓層中有多少個房間有樓梯

        for(j=first;j<m;j++)  //從起點到m號

        if(rooms[i][j].flag==1)  //如果有樓梯

        {

            stair_tot++;  //有樓梯的房間數+1

            room_num[stair_tot]=j;  //存入陣列

        }

        for(j=0;j<first;j++)  //走完一圈

        if(rooms[i][j].flag==1)

        {

            stair_tot++;

            room_num[stair_tot]=j;

        }

        key+=rooms[i][first].num; key%=20123;  //別忘了取模

        rooms[i][first].num%=stair_tot;  //不要不停地繞

        if(rooms[i][first].num==0)rooms[i][first].num=stair_tot;  //注意!!!沒有第零個,應為該樓層的最後一個

        first=room_num[rooms[i][first].num]; i++;  //first更新,樓層數+1

    }

    cout<<key<<endl;  //輸出

    return 0;

}