HDU 5155 Harry And Magic Box dp
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5155
题意:
给n*m的零一矩阵,问它的左视图和正视图都为全1的所有情况。
题解:
n,m不超过50,所以可以跑O(n^4);
另dp[i][j]代表前i行(每一行至少放一个,因为这样就可以只考虑列会不会为空就可以了)中有j列不全为0,那么有状态转移方程:
dp[i][k]+=dp[i-1][j]*C[m-j][k-j]*C[j][t](0<=t<=j)
C[i][j]表示i个方格中j个为1的所有情况。(组合数,可递推离线处理出来)
(题外话:原先以为要和TSP一样,要用集合来表示状态,但其实它这里填的位置不连续其实没有影响,因为它等价于连续的情况。)
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 typedef __int64 LL; 6 7 const int maxn = 55; 8 const int mod = 1e9 + 7; 9 10 int n, m; 11 LL dp[maxn][maxn]; 12 13 LL C[maxn][maxn]; 14 void get_c() { 15 for (int i = 0; i < maxn; i++) { 16 C[i][0] = 1; 17 for (int j = 1; j <= i; j++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod; 18 } 19 } 20 21 void init() { 22 memset(dp,0,sizeof(dp)); 23 } 24 25 int main() { 26 get_c(); 27 while (scanf("%d%d", &n, &m) == 2 && n) { 28 init(); 29 for (int j = 1; j <= m; j++) dp[1][j] = C[m][j]; 30 for (int i = 2; i <= n; i++) { 31 for (int j = 1; j <= m; j++) { 32 for (int k = j; k <= m; k++) { 33 for (int t = 0; t <= j; t++) { 34 if (k == j&&t == 0) continue; 35 dp[i][k] += dp[i - 1][j] * C[m - j][k - j] % mod*C[j][t] % mod; 36 dp[i][k] %= mod; 37 } 38 } 39 } 40 } 41 printf("%lld\n", dp[n][m]); 42 } 43 return 0; 44 }