<NOI2001>炮兵阵地

一如既往的dp

emm调了很久

还是我太low

本来想不瞅题解,自己yy出来

然而失败了

难过

 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
",ans);
65 return 0;
66 }
点击查看丑陋の代码&注释

 

 

原文地址:https://www.cnblogs.com/pile8852/p/9296986.html