Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5079 Accepted Submission(s): 2628
InputThe input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases.
OutputFor each case, you should print the desired number of ways in one line. It is guaranteed, that it does not exceed 263 – 1. Use the format in the sample.
Sample Input26 31 1 11 0 11 1 11 1 11 0 11 1 12 41 1 1 11 1 1 1
Sample OutputCase 1: There are 3 ways to eat the trees.Case 2: There are 2 ways to eat the trees.
Source2008 “Sunline Cup” National Invitational Contest
Recommendwangye | We have carefully selected several similar problems for you: 1691 1695 1689 1692 1690
如上图,每根红线代表的是插头DP中状态的每一位,特别的地方就在最后一位,那条横线,表示的是当前格子被更新时左边是否有向右的插头,而当前格子上面的竖线表示上面是否有向下的插头...
这样,插头DP的状态就比普通轮廓线多一位。
这两个位置就是转移的重点。
在当前格子上面有插头或者左边有插头,那么可以转移到当前向右或者向下;如果两个状态同时存在,那么将两个状态合并,不能新增插头;如果两个状态都不存在,并且没有障碍格,那么同时增加两个新插头。
第一列、最后一排、最后一列需要特判。
空间要开足!!!
Code
#include<bits/stdc .h>#define LL long longusing namespace std;int n, m, G[12][12], ti;LL dp[2][(1 << 12)];int main() { int T; scanf("%d", &T); while(T --) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ) for(int j = 1; j <= m; j ) scanf("%d", &G[i][j]); memset(dp, 0, sizeof(dp)); int now = 0; dp[now][0] = 1; for(int i = 1; i <= n; i ) { for(int j = 1; j <= m; j ) { now ^= 1; memset(dp[now], 0, sizeof(dp[now])); for(int s = 0; s < (1 << m 1); s ) { int pre = s & (1 << m); int las = s & 1; if(!G[i][j]) { int ss = (s << 1); if(!pre && !las) dp[now][ss] = dp[now ^ 1][s]; } else { if(j != 1) { if(pre && las) { int ss = (s ^ pre ^ las) << 1; dp[now][ss] = dp[now ^ 1][s]; } if(pre && !las) { int ss = (s ^ pre) << 1 | 1; if(j != m) dp[now][ss] = dp[now ^ 1][s]; ss = (s ^ pre) << 1 | 2; if(i != n) dp[now][ss] = dp[now ^ 1][s]; } if(!pre && las) { int ss = (s ^ las) << 1 | 1; if(j != m) dp[now][ss] = dp[now ^ 1][s]; ss = (s ^ las) << 1 | 2; if(i != n) dp[now][ss] = dp[now ^ 1][s]; } if(!pre && !las) { int ss = s << 1 | 3; dp[now][ss] = dp[now ^ 1][s]; } } else if(j == 1 && !las) { if(pre) { int ss = (s ^ pre) << 1 | 2; if(i != n) dp[now][ss] = dp[now ^ 1][s]; ss = (s ^ pre) << 1 | 1; if(j != m) dp[now][ss] = dp[now ^ 1][s]; } else { if(i != n && j != m) { int ss = s << 1 | 3; dp[now][ss] = dp[now ^ 1][s]; } } } } } } } printf("Case %d: There are %lld ways to eat the trees.\n", ti, dp[now][0]); }}
来源:http://www.icode9.com/content-4-54751.html
联系客服