NOIP201605玩具謎題-解題報告c++
2019-11-07 14:14 數組
Part 1原題:函數
小南有一套可愛的玩具小人,它們各有不一樣的職業。spa
有一天,這些玩具小人把小南的眼鏡藏了起來。小南發現玩具小人們圍成了一個圈,它們有的面朝圈內,有的面朝圈外。 以下圖:code
這時singer 告訴小南一個迷題:「眼鏡藏在我左數第 3 個玩具小人的右數第 1 個玩具小人的左數第 2 個玩具小人裏。 」
小南發現,這個迷題中玩具小人的朝向很是關鍵,由於朝內和朝外的玩具小人的左右方向是相反的:面朝圈內的玩具小人,它的左邊是順時針方向,右邊是逆時針方向;而面向圈外的玩具小人,它的左邊是逆時針方向,右邊是順時針方向。
小南一邊艱難地辨認着玩具小人,一邊數着:blog
「singer 朝內,左數第 3 個是archer。ci
「archer 朝外,右數第 1 個是thinker。字符串
「thinker 朝外,左數第 2 個是writer。get
「因此眼鏡藏在writer 這裏! 」
雖然成功找回了眼鏡,但小南並無放心。 若是下次有更多的玩具小人藏他的眼鏡,或是迷題的長度更長,他可能就沒法找到眼鏡了。 因此小南但願你寫程序幫他解決相似的迷題。這樣的迷題具體能夠描述爲:
有 n 個玩具小人圍成一圈,己知它們的職業和朝向。 如今第 1 個玩具小人告訴小 南一個包含 m 條指令的迷題,其中第 i 條指令形如「左數/右數第 si 個玩具小人」。 你須要輸出依次數完這些指令後,到達的玩具小人的職業。it
Part 2:思路
這道題目的關鍵是小人的朝向。
若是這些方向你都處理好了,那麼就能AC了。
下面先粘一個超時代碼:
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct toy 4 { 5 int dir; 6 char name[101]; 7 }a[10001]; 8 int i,j; 9 int now; 10 int m,n; 11 int init() 12 { 13 int x=0,f=1; 14 char c=getchar(); 15 while(c<'0'||c>'9') 16 { 17 if(c=='-') f=-1; 18 c=getchar(); 19 } 20 while(c>='0'&&c<='9') 21 { 22 x=x*10+c-'0'; 23 c=getchar(); 24 } 25 return x*f; 26 } 27 int main() 28 { 29 n=init(); 30 m=init(); 31 for(i=0;i<n;i++) 32 { 33 a[i].dir=init(); 34 scanf("%s",&a[i].name); 35 } 36 int x,y; 37 now=0; 38 for(i=1;i<=m;i++) 39 { 40 x=init(); 41 y=init(); 42 if(a[now].dir==0 && x==0) now=(now+n-y)%n; 43 else if(a[now].dir==0 && x==1) now=(now+y)%n; 44 else if(a[now].dir==1 && x==0) now=(now+y)%n; 45 else if(a[now].dir==1 && x==1) now=(now+n-y)%n; 46 } 47 printf("%s",&a[now].name); 48 return 0; 49 }
這個代碼之因此超時,是由於它的處理部分(line43-45)的處理效率太低,下面粘AC代碼:
#include<bits/stdc++.h>//萬能頭文件,這裏偷了個懶 : ) using namespace std;//對於bits/stdc++.h來講,這句話是必要的,但對於某些頭文件好比stdio.h來講,這句話不能寫 int main()//main函數 { int n,m;//n個小人,m條線索 scanf("%d%d",&n,&m);//讀入 bool a[100000];//這裏的a[i]用來記錄第i個小人的臉的朝向 char b[100000][11];//由於每一個名字都是一個字符串,因此這裏的b數組(串)要用二維的 for(int i=0;i<n;i++)//循環從1到n,循環輸入每一個小人 { scanf("%d%s",&a[i],&b[i]); } int c[100000];//這裏的c數組用來記錄每條線索的的距離,例如 1 3中的3 for(int i=0;i<m;i++)//循環每條線索 { int t;//定義臨時變量t,用來記錄這條線索的行駛方向 cin>>t;//讀入方向 cin>>c[i];//讀入這條線索的距離 if(t==1) c[i]*=-1; //這裏,若是方向是 ‘右’,則將它乘上-1,方便後面累加和統計 } int pos=0;//定義位置變量(position),初始設爲0 for(int i=0;i<m;i++)//循環每條線索進行處理 { if(a[pos]==0) c[i]*=-1;//若是小人方向是 ‘左’,則將它乘上-1,方便後面累計和統計 pos+=c[i];//對於每一個線索,若是他的方向是左,那他的距離已經乘上-1了, 因此直接加上 if(pos>n-1) pos-=n;//若是他的越界方式是過於大,因此應該減去n,其功效相似於%n if(pos<0) pos+=n;//若是他的越界方式是過於小,因此應該加上n,其功效相似於%n } cout<<b[pos];//輸出當前位置上的小人的名字。 return 0; }
註釋已經寫上了,各位本身能夠看。