Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 23094 | Accepted: 8948 |
Description
Input
Output
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
Source
题意就不用解释了吧
思路:从上往下遍历,因为炮弹能不能放取决于前两行的状态,所以要定义一个3维数组 dp[i][j][k] , i 表示该行, j表示满足情况的该行的状态,
k 表示上一行的状态,所以dp[i][j][k] += max(dp[i - 1][k][kk]), kk为上上一行满足情况的状态,
最后只要求max(dp[n][][])的最大值即可
<pre name="code" class="cpp">#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<set> #include <queue> #include<algorithm> #include <vector> const double PI = acos(-1.0); using namespace std; int dp[105][66][66]; int s[100]; int tot; int a[105][15]; char str[105][15]; const int mod = 100000000; void init() //先预处理出一行所有能行的情况 { tot = 0; for(int i = 0; i < (1 << 10); ++ i) { if((i & (i << 1)) == 0 && (i & (i << 2)) == 0) s[tot ++] = i; } s[tot ++] = 2000; //开大一个, 防止下面m == 10是 s[i] < (1 << m)会无限循环下去而超时。 //printf("%d\n", tot); } int main() { int n, m, i, j, k; init(); while(~scanf("%d%d", &n, &m)) { for(i = 1; i <= n; ++ i) { scanf("%s", str[i] + 1); for(j = 1; j <= m; ++ j) { if(str[i][j] == 'P') a[i][j] = 1; else a[i][j] = 0; } } memset(dp, 0, sizeof(dp)); for(i = 1; i <= n; ++ i) { for(j = 0; s[j] < (1 << m) ; ++ j) { int res = 1; for(k = 1; k <= m; ++ k) //判断状态j是否满足输入情况 { if(a[i][k] == 0 && ((1 << (k - 1)) & s[j])) { res = 0; break; } } if(!res) continue; //求在没考虑上上行的情况下求dp if(i == 1) { for(k = 0; s[k] < (1 << m); ++ k) //第一行不受上行限制,所以上行的所以状态都满足 { for(int kk = 0; kk < m; ++ kk) { if(((1 << kk) & s[j])) dp[i][j][k] ++ ; } //printf("%d\n", k); } } else { for(int kk = 0; s[kk] < (1 << m); ++ kk) { if((s[kk] & s[j]) == 0) //判断上行是否满足 { for(k = 0; k < m; ++ k) { if(((1 << k) & s[j])) dp[i][j][kk] ++ ; } } } } //累加上上满足情况的dp if(i == 2) { for(k = 0; s[k] < (1 << m); ++ k) { int mm = 0; if((s[k] & s[j])) continue; for(int kk = 0; s[kk] < (1 << m); ++ kk) { if(dp[i - 1][k][kk] > mm) mm = dp[i - 1][k][kk]; } dp[i][j][k] += mm; } } else if(i > 2) { for(k = 0; s[k] < (1 << m); ++ k) { int mm = 0; if((s[k] & s[j])) continue; for(int kk = 0; s[kk] < ( 1 << m); ++ kk) { if(dp[i - 1][k][kk] > mm && (s[kk] & s[j]) == 0 && (s[kk] & s[k]) == 0) { mm = dp[i - 1][k][kk]; } } dp[i][j][k] += mm; } } } } int ans = 0; for(i = 0; s[i] < (1 << m); ++ i) { for(j = 0; s[j] <(1 << m); ++ j) { ans = max(ans, dp[n][i][j]); //printf("%d\n", dp[n][i][j]); } } printf("%d\n", ans); } } /* 12 9 HPHHPHHPH PPPHHPPHP HHPHHHHPP PHHHHPHHP HHHPHPHHH HPHPPPPPP PPPHHPPPP HPHPHHHPH PPHPPPHPH PHPHPPPHP HPHHPHHPH HPPPHHPHH 25 1 10 PPPPPPPPPP 4 2 10 PPPPPPPPPP PPPPPHPPPP 7 */