Martian Sunrise(状态压缩+位运算)
题意:给你一个曲谱由音符组成 曲谱长度是n,有m行,每行有7个音符。一个演奏家可以演奏任意两行的所有音符。曲谱按顺序演奏,问你至少需要几个演奏家,可以把曲谱演奏完。
分析:状态压缩,把字符串化成数,用二进制的或与完成,具体见代码
AC_Code:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e4+10; 5 const int inf=0x3f3f3f3f; 6 #define rep(i,first,last) for(int i=first;i<=last;i++) 7 #define dep(i,first,last) for(int i=first;i>=last;i--) 8 int a[17], song[maxn]; 9 int n,m; 10 char s[5]; 11 int ans; //记录演奏家个数 12 int getid(char *s){ 13 int t=(s[0]-'A')*3;//为什么*3呢?,因为s[1]=='b'的时候要+1,s[1]=='#'的时候要+2 14 if( s[1]=='\0') return t; 15 else if( s[1]=='b' ) return t+1; 16 else return t+2; 17 } 18 19 int main() 20 { 21 scanf("%d",&m); 22 rep(i,0,m-1){ 23 rep(j,0,6){ 24 scanf("%s",s); 25 a[i] |= 1<<getid(s); //把每行的音符压缩成数字,或即是并 26 } 27 } 28 scanf("%d",&n); 29 rep(i,0,n-1){ //乐谱压缩成数字 30 scanf("%s",s); 31 song[i]=getid(s); 32 } 33 int pos=0,k; 34 while(1){ 35 ans++; 36 int Mpos=0; //记录弹的最远的地方 37 rep(i,0,m-1){ //暴力枚举演奏家的两行 38 rep(j,0,m-1){ 39 k=pos; 40 while(k<n){ //看最远可以弹到哪里 41 if((a[i]&(1<<song[k])) || (a[j]&(1<<song[k]))) k++;//与即是求交,与出来不为0,说明有可弹奏的音符 42 else break; 43 } 44 Mpos=max(Mpos,k); 45 if( Mpos==n ) break;//如果已经弹完,直接退出即可 46 } 47 if( Mpos==n ) break; 48 } 49 pos=Mpos; 50 if( Mpos==n ) break; 51 } 52 printf("%d\n",ans); 53 return 0; 54 }