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
", dp[n][m]);
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/fenice/p/5451712.html