状压DP。。。没好好去想转移方程推掉了重写QAQ
对状态数目的优化还是挺牛的orz
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#include<bits/stdc++.h> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<queue> 6 #include<algorithm> 7 #define inc(i,l,r) for(int i=l;i<=r;i++) 8 #define dec(i,l,r) for(int i=l;i>=r;i--) 9 #define link(x) for(edge *j=h[x];j;j=j->next) 10 #define mem(a) memset(a,0,sizeof(a)) 11 #define inf 1e9 12 #define ll long long 13 #define succ(x) (1<<x) 14 #define NM 60+5 15 using namespace std; 16 int read(){ 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 19 while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); 20 return x*f; 21 } 22 bool _read(){ 23 char c=getchar(); 24 while(c!='P'&&c!='H')c=getchar(); 25 return c=='H'; 26 } 27 int d[105][NM][NM],c[NM],b[NM],n,m,a[105],s,ans; 28 int cou(int t){ 29 int s=0; 30 inc(j,0,10) 31 if(t&succ(j))s++; 32 return s; 33 } 34 int main(){ 35 n=read();m=read(); 36 inc(i,1,n) 37 inc(j,1,m) 38 if(_read())a[i]+=succ(j-1); 39 inc(t,0,succ(m)-1) 40 if(!(t&(t<<1))&&!(t&(t<<2))) 41 b[++s]=t,c[s]=cou(t); 42 if(n==1){ 43 inc(i,1,s) 44 if(!(b[i]&a[1])) 45 ans=max(ans,c[i]); 46 printf("%d\n",ans); 47 return 0; 48 } 49 inc(t,1,s) 50 if(!(b[t]&a[2])){ 51 inc(v,1,s) 52 if(!(b[v]&a[1])&&!(b[v]&b[t])) 53 d[2][t][v]=c[t]+c[v]; 54 } 55 inc(i,3,n) 56 inc(t,1,s) 57 if(!(b[t]&a[i])){ 58 inc(v,1,s) 59 if(!(b[v]&b[t])&&!(b[v]&a[i-1])){ 60 d[i][t][v]=c[t]+c[v]; 61 inc(j,1,s) 62 if(d[i-1][v][j]&&!(b[t]&b[j])&&!(b[j]&a[i-2])) 63 d[i][t][v]=max(d[i][t][v],d[i-1][v][j]+c[t]); 64 } 65 } 66 inc(i,1,s) 67 inc(j,1,s) 68 ans=max(ans,d[n][i][j]); 69 printf("%d\n",ans); 70 return 0; 71 }