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