五、樂譜變調(30分 1-4資料5分,最後一個資料10分)
輸入文件:music.in
輸出文件:music.out
【問題描述】
大家應該聽過很多美妙動聽的歌曲,也曾經在卡拉OK中唱過不少歌曲。其實,很多歌曲的調子都經過了變調,因為很多歌曲原來的調子一般都偏高,需要把調適當降低,才適合一般人歌唱。現在請你編程解決這個變調的問題,把一個曲譜從原來的調子基礎上,升高或降低若干個調,變成一個新的曲譜。
【音階】
相信大家都見過電子琴,也聽過電子琴,琴中的每個白色鍵,代表的是簡譜中的1,2,3,4,5,6,7的音階,用字母代表即為 C,D,E,F,G,A,B,見下圖:
此外,上面的黑鍵表示半音,按照上圖,從左邊到右邊的5個黑鍵代表的半音為:#C,#D,#F,#G,#A
由最左邊的音階C數起到第七個音階B,中間的黑鍵和鍵,均處於一個基準八度區域,在B右邊的琴鍵,比原來的音階高一個八度區域,稱為高八度區域; C音階左邊的琴鍵(圖片沒有顯示),比原來的音階低一個八度區域,稱為低八度區域。
【樂譜】
一個歌曲的樂譜,包括音階、節奏、小節線、休止符等元素,這裡為了簡單表示,只保留音階這一元素,節奏、小節線、休止符不在此題目中展現。
樂譜中的每個音階,可以用C,D,E,F,G,A,B,#C,#D,#F,#G,#A 表示。
在樂譜中會牽涉到八度區域的遷移問題,我們使用 “>”、“<” 來變化當前的八度區域。其中“>”表示提高當前八度區域(例如從低八度區域=>基準八度區域),“<”表示降低當前八度區域(例如高八度區域=>基準八度區域)。樂譜一開始的時候,當前八度區域為基準八度區域。
【樂譜變調】
對一個樂譜,提高或者降低N個半音的操作,成為樂譜變調。
首先,對於一個八度區域中,以下音階均相隔一個半音。
C,#C,D,#D,E,F,#F,G,#G,A,#A,B
然後,B音階比高它一個八度區域的C音階,相隔一個半音
變調就是一個簡單的升降音階的操作,只要數著半音階個數修改音階即可。例如,C音階提高6個半音,數過去就是#F,B音階提高4個音階,則為下一個八度區域的 #D 音階,同理,#F降6個半音階(升-6個半音)則為C。
【輸入格式】
輸入第一行字元串,包含上面的各個音階,以及>/<符號,表示一個樂譜,樂譜字元串長度<=200,沒有空格和其他字元串。
輸入第二行為整數N (-16<=N<=16) ,表示升多少個半音
【輸出格式】
輸出為一行字元串,代表樂譜。
【輸入樣例】
CDEFGAB>C
2
【輸出樣例】
DE#FGAB>#CD
【分析】
看著題目挺花哨,其實很簡單,就是一個模擬,只要讀請題目一般都能滿分。
【我的代碼】
001 /*
002 *Problem: GDOI2011 Music
003 *Author: Yee-fan Zhu
004 *Email: zyfworks@gmail.com
005 */
006 #include <cstdlib>
007 #include <iostream>
008 #include <cstdio>
009 #include <cstring>
010 using namespace std;
011 int N;
012
013 int num[300];
014 int M=0;
015
016 int Hash(char a,char b)
017 {
018 if(a=='C' && b=='0') return 1;
019 if(a=='#' && b=='C') return 2;
020 if(a=='D' && b=='0') return 3;
021 if(a=='#' && b=='D') return 4;
022 if(a=='E' && b=='0') return 5;
023 if(a=='F' && b=='0') return 6;
024 if(a=='#' && b=='F') return 7;
025 if(a=='G' && b=='0') return 8;
026 if(a=='#' && b=='G') return 9;
027 if(a=='A' && b=='0') return 10;
028 if(a=='#' && b=='A') return 11;
029 if(a=='B' && b=='0') return 12;
030 return 0;
031 }
032
033 void print(int a)
034 {
035 if(a==1) printf("C");
036 if(a==2) printf("#C");
037 if(a==3) printf("D");
038 if(a==4) printf("#D");
039 if(a==5) printf("E");
040 if(a==6) printf("F");
041 if(a==7) printf("#F");
042 if(a==8) printf("G");
043 if(a==9) printf("#G");
044 if(a==10) printf("A");
045 if(a==11) printf("#A");
046 if(a==0) printf("B");
047 }
048
049 void init()
050 {
051 char str[300];
052 scanf("%s\n%d\n",&str,&N);
053 int len=strlen(str);
054 int top=0;
055 int now=2;
056 while(top<len)
057 {
058 char c=str[top];
059 if(c=='#')
060 {
061 int res=(now-1)*12+Hash(c,str[top+1]);
062 num[++M]=res;
063 top+=2;
064 continue;
065 }
066 if(c=='>')
067 {
068 now++;
069 top++;
070 continue;
071 }
072 if(c=='<')
073 {
074 now--;
075 top++;
076 continue;
077 }
078
079 int res=(now-1)*12+Hash(c,'0');
080 num[++M]=res;
081 top++;
082 continue;
083 }
084 }
085
086 void work()
087 {
088 for (int i=1;i<=M;i++)
089 num[i]+=N;
090 int now=2;
091 int up=25;
092 int down=12;
093 for(int i=1;i<=M;i++)
094 {
095 int tmp=num[i];
096 if(tmp<=down)
097 {
098 now--;
099 down-=12;
100 up-=12;
101 printf("<");
102 print(tmp%12);
103 continue;
104 }
105 if(tmp>=up)
106 {
107 now++;
108 down+=12;
109 up+=12;
110 printf(">");
111 print(tmp%12);
112 continue;
113 }
114 print(tmp%12);
115 }
116 }
117
118 int main()
119 {
120 freopen("music.in","r",stdin);
121 freopen("music.out","w",stdout);
122 init();
123 work();
124 return 0;
125 }