题意:
中文题意,略。
思路:
一支炮兵部队可以攻击的范围是两格,所以当前行的状态只和前两行的状态有关。
所以就枚举当前行,前一行和前两行的状态,如果用二进制枚举,2^M的三次方,M最大为10,铁定TLE。
其实状态并没有想的那么多,因为隔两格才可以放一个,所以其实真的有效的状态不会超过100个。
100的三次方就可以接受。
另外,为了节省时间以及方便处理,那么可以将输入的状态压缩为2进制。
还有就是,答案最后再找吧。。。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 using namespace std; 6 const int N = 200; 7 int dp[105][N][N]; 8 int num[1<<12]; 9 char mp[105][N]; 10 int mmp[105]; 11 vector<int> g; 12 int n,m; 13 int cal(int x) 14 { 15 int cnt = 0; 16 while (x) 17 { 18 if (x&1) cnt++; 19 x >>= 1; 20 } 21 return cnt; 22 } 23 bool judge(int x) 24 { 25 if (x & (x<<1)) return 0; 26 if (x & (x<<2)) return 0; 27 return 1; 28 } 29 int main() 30 { 31 while (scanf("%d%d",&n,&m)!=EOF) 32 { 33 memset(mmp,0,sizeof(mmp)); 34 memset(num,0,sizeof(num)); 35 memset(dp,0,sizeof(dp)); 36 g.clear(); 37 for (int i = 0;i < n;i++) 38 { 39 scanf("%s",mp[i]); 40 for (int j = 0;j < m;j++) 41 { 42 if (mp[i][j] == 'H') mmp[i] |= (1 << j); 43 } 44 } 45 for (int i = 0;i <(1<<m);i++) 46 { 47 if (judge(i)) g.push_back(i); 48 num[i] = cal(i); 49 } 50 int ans = 0; 51 for (int i = 0;i < g.size();i++) 52 { 53 if (g[i]&mmp[0]) continue; 54 dp[0][i][0] = max(dp[0][i][0],num[g[i]]); 55 } 56 for (int i = 0;i < g.size();i++) 57 { 58 for (int j = 0;j < g.size();j++) 59 { 60 int x = g[i],y = g[j]; 61 if (x&y) continue; 62 if (y&mmp[1]) continue; 63 dp[1][j][i] = max(dp[1][j][i],dp[0][i][0]+num[y]); 64 } 65 } 66 for (int i = 0;i < n - 2;i++) 67 { 68 for (int j = 0;j < g.size();j++) 69 { 70 for (int k = 0;k < g.size();k++) 71 { 72 for (int l = 0;l < g.size();l++) 73 { 74 int x = g[j],y = g[k],z = g[l]; 75 if (x&z) continue; 76 if (x&y) continue; 77 if (y&z) continue; 78 if (z&mmp[i+2]) continue; 79 dp[i+2][l][k] = max(dp[i+2][l][k],dp[i+1][k][j] + num[z]); 80 } 81 } 82 } 83 } 84 for (int i = 0;i < g.size();i++) 85 { 86 for (int j = 0;j < g.size();j++) 87 { 88 int x = g[i],y = g[j]; 89 if (x&y) continue; 90 if (mmp[n-1]&y) continue; 91 ans = max(ans,dp[n-1][j][i]); 92 } 93 } 94 printf("%d ",ans); 95 } 96 return 0; 97 }