<NOI2001>炮兵阵地
一如既往的dp
emm调了很久
还是我太low了
本来想不瞅题解,自己yy出来
然而失败了
难过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 int n,m,cnt=1,tot=0; 7 int map[105],dp[105][100][100],mark[105],num[105];//map保存图的0101模式//dp第i行在状态j前一行状态为k时 最多...//mark标记是否为可行状态 8 char s[15]; 9 10 void init() 11 { 12 int i,maxx=(1<<m); 13 for (i=0;i<maxx;i++) 14 if ( (!(i&(i<<1))) && (!(i&(i<<2))) ) 15 { 16 mark[++tot]=i; 17 int t=i; 18 while(t) num[tot]+=(t&1),t>>=1; 19 } 20 } 21 bool OK(int a,int b){return !(mark[a]&map[b]);}//如果有1在一块儿,!()返回0 22 23 int main() 24 { 25 int i,j,ans=-1; 26 scanf("%d%d",&n,&m); 27 memset(dp,0,sizeof(dp)); 28 init(); 29 gets(s); 30 for (i=1;i<=n;i++) 31 { 32 gets(s); 33 for (j=1;j<=m;j++) 34 if (s[j-1]=='H') 35 map[i]+=(1<<(m-j)); 36 } 37 38 for(i=1;i<=tot;i++) if(OK(i,1)) dp[1][i][0]=num[i],ans=max(ans,dp[1][i][0]);//预处理第1行 39 40 for(i=1;i<=tot;i++)//预处理第2行 41 { 42 if(!OK(i,2))continue; 43 for(j=1;j<=tot;j++) if(OK(j,1) && (!(mark[i]&mark[j]))) dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+num[i]),ans=max(ans,dp[2][i][j]); 44 } 45 46 for(i=3;i<=n;i++) 47 for(int now=1;now<=tot;now++)//枚举本行 48 { 49 if(!OK(now,i))continue; 50 for(int last=1;last<=tot;last++)//枚举上一行 51 { 52 if(mark[now]&mark[last])continue; 53 if(!OK(last,i-1))continue; 54 for(int llast=1;llast<=tot;llast++)//枚举上上行 55 { 56 if( (mark[now]&mark[llast]) || (mark[last]&mark[llast]) )continue; 57 if(!OK(llast,i-2))continue; 58 dp[i][now][last]=max(dp[i][now][last],dp[i-1][last][llast]+num[now]); 59 } 60 } 61 } 62 for(int now=1;now<=tot;now++) 63 for(int last=1;last<=tot;last++)ans=max(ans,dp[n][now][last]); 64 printf("%d\n",ans); 65 return 0; 66 }