zoukankan      html  css  js  c++  java
  • ZOJ 2563 Long Dominoes(状压DP)

    给定一个m*n的方格子,要求用3*1的骨牌去覆盖,骨牌可以用横放或者竖放,问最终有多少种放置方式,将其铺满。

    分析:由于最多30行,每行最多9列,所以可以按行来dp,设计每行的状态从而进行转移,考虑每个骨牌放置对下一行的影响,共有0,1,2,3种方式,0对应横放或者竖放时最下面那

    个格子,此行对下一行没有影响,1,竖放时第1个,2竖放时第2个,这样进行转移。注意,第i行横放时要求上一行相应位置状态为0。

    思路及代码都来自这里,其实不会做这题,看了才了解。

    代码:

     1 #include <bits/stdc++.h>
     2 #define pb push_back
     3 #define mp make_pair
     4 #define esp 1e-14
     5 #define lson   l, m, rt<<1
     6 #define rson   m+1, r, rt<<1|1
     7 #define sz(x) ((int)((x).size()))
     8 #define pf(x) ((x)*(x))
     9 #define pb push_back
    10 #define in freopen("solve_in.txt", "r", stdin);
    11 #define bug(x) printf("Line : %u >>>>>>
    ", (x));
    12 #define inf 0x0f0f0f0f
    13 using namespace std;
    14 typedef long long LL;
    15 typedef map<LL, int> MPS;
    16 typedef pair<LL, LL> PII;
    17 const int maxn = 20000;
    18 LL dp[33][maxn];
    19 int st[10];
    20 int n, m;
    21 void pre() {
    22     st[0] = 1;
    23     for(int i = 1; i <= 9; i++)
    24         st[i] = st[i-1]*3;
    25 }
    26 int dig[20];
    27 void getDig(int x) {
    28     int len = 0;
    29     memset(dig, 0, sizeof dig);
    30     while(x) {
    31         dig[len++] = x%3;
    32         x /= 3;
    33     }
    34 }
    35 void dfs(int cur, int state, int base, int prestate) {
    36     if(cur == n) {
    37         dp[base][state] += dp[base-1][prestate];
    38         return;
    39     }
    40     if(dig[cur] == 0) {
    41         if(cur+2 < n && dig[cur+1] == 0 && dig[cur+2] == 0) {
    42             dfs(cur+3, state, base, prestate);
    43         }
    44         dfs(cur+1, state+st[cur], base, prestate);
    45     } else if(dig[cur] == 1) {
    46         dfs(cur+1, state+2*st[cur], base, prestate);
    47     } else {
    48         dfs(cur+1, state, base, prestate);
    49     }
    50 }
    51 int main() {
    52 //    in
    53     pre();
    54     while(scanf("%d%d", &n, &m), n || m) {
    55         if(n*m%3) {
    56             puts("0");
    57             continue;
    58         }
    59         memset(dp, 0, sizeof dp);
    60         dp[0][0] = 1;
    61         for(int i = 1; i <= m; i++) {
    62             for(int j = 0; j < st[n]; j++) {
    63                 if(dp[i-1][j]) {
    64                     getDig(j);
    65                     dfs(0, 0, i, j);
    66                 }
    67             }
    68         }
    69         printf("%lld
    ", dp[m][0]);
    70     }
    71     return 0;
    72 }
    View Code

     另一道类似的题目:HDU 4804 Campus Design

    题意是:n*m的格子,用1*1和1*2的骨牌覆盖,但是有一些格子不需要覆盖,而且最终要求所用的1*1的骨牌个数num满足:c <= num <= d.

    解法类似,每个格子被覆盖的情况有两种,0和1,即1*2格子竖放的第一个,1*2格子竖放第2个或者1*1格子,或者不需要覆盖,这样按行进行转移就行了。

    代码:

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <map>
     7 #include <vector>
     8 #define pb push_back
     9 #define mp make_pair
    10 #define esp 1e-14
    11 #define lson   l, m, rt<<1
    12 #define rson   m+1, r, rt<<1|1
    13 #define sz(x) ((int)((x).size()))
    14 #define pf(x) ((x)*(x))
    15 #define pb push_back
    16 #define in freopen("solve_in.txt", "r", stdin);
    17 #define bug(x) printf("Line : %u >>>>>>
    ", (x));
    18 #define inf 0x0f0f0f0f
    19 using namespace std;
    20 typedef long long LL;
    21 typedef map<LL, int> MPS;
    22 typedef pair<LL, LL> PII;
    23 
    24 const int M = (int)1e9 + 7;
    25 const int maxn = 110;
    26 const int maxm = 1111;
    27 
    28 LL dp[maxn][23][maxm];
    29 int n, m, c, d;
    30 char maze[maxn][11];
    31 int dig[11];
    32 
    33 void getDig(int x) {
    34     memset(dig, 0, sizeof dig);
    35     int len = 0;
    36     while(x) {
    37         dig[len++] = x&1;
    38         x >>= 1;
    39     }
    40 }
    41 bool check(char *s, int x) {
    42     for(int i = 0; s[i]; i++) {
    43         if((x&1) && s[i] == '0') return false;
    44         x >>= 1;
    45     }
    46     return true;
    47 }
    48 void dfs(int pre, int num, int st, int cur, int state, int cnt) {
    49     if(cnt > d) return;
    50     if(cur == m) {
    51         dp[pre+1][cnt][state] = (dp[pre+1][cnt][state]+dp[pre][num][st])%M;
    52         return;
    53     }
    54     if(maze[pre+1][cur] == '0') {
    55         dfs(pre, num, st, cur+1, state, cnt);
    56     } else if(dig[cur] == 0) {
    57         if(cur+1 < m && dig[cur+1] == 0 && maze[pre+1][cur+1] == '1')
    58             dfs(pre, num, st, cur+2, state, cnt);
    59         if(pre+1 < n && maze[pre+2][cur] == '1')
    60         dfs(pre, num, st, cur+1, state+(1<<cur), cnt);
    61         dfs(pre, num, st, cur+1, state, cnt+1);
    62     } else {
    63         dfs(pre, num, st, cur+1, state, cnt);
    64     }
    65 }
    66 int main() {
    67     
    68     while(scanf("%d%d%d%d", &n, &m, &c, &d) == 4) {
    69         memset(dp, 0, sizeof dp);
    70         for(int i = 1; i <= n; i++)
    71             scanf("%s", maze[i]);
    72         dp[0][0][0] = 1;
    73         for(int i = 0; i < n; i++) {
    74             int j;
    75             if(i == 0) {
    76                 j = 0;
    77                 getDig(j);
    78                 int x = 0;
    79                 if(dp[i][x][j])
    80                     dfs(i, x, j, 0, 0, x);
    81             } else {
    82                 for(int j = 0; j < (1<<m);  j++) {
    83                     if(check(maze[i], j) == false) continue;
    84                     getDig(j);
    85                     for(int x = 0; x <= d; x++) if(dp[i][x][j])
    86                             dfs(i, x, j, 0, 0, x);
    87                 }
    88             }
    89         }
    90         LL ans = 0;
    91         for(int i = c; i <= d; i++)
    92             ans = (ans + dp[n][i][0])%M;
    93         printf("%lld
    ", ans);
    94     }
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    @SuppressWarnings("resource")
    连续根据两个字段排序
    java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误
    java中数组的定义
    单表(多表需手动创建多个转换)插入,更新数据
    批量处理sql
    查询排序后前5名的信息
    面向对象详细
    Flask-SQLAlchemy
    Dbutils-数据库连接池
  • 原文地址:https://www.cnblogs.com/rootial/p/4161742.html
Copyright © 2011-2022 走看看