Martian Sunrise(状态压缩+位运算)

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 }

猜你喜欢

转载自www.cnblogs.com/wsy107316/p/12371253.html