HDU 4804 Campus Design

来源:互联网 发布:swift for windows 编辑:程序博客网 时间:2024/05/29 02:29
轮廓线动态规划.状态比较好想,注意转移状态以及位运算.状态转移方式见代码.
#include <cstdio>#include <cstring>const int MOD = 1000000007;inline void add(int &x, int y){    x += y;    while (x >= MOD)    x -= MOD;}int dp[2][1 << 10][25];int map[105][15];int n, m, c, d;void cal_dp(){    memset(dp, 0, sizeof(dp));    int cur = 0;    dp[0][(1 << m) - 1][0] = 1;    for (int i = 0; i < n; i ++) {        for (int j = 0; j < m; j ++) {            cur ^= 1;            memset(dp[cur], 0, sizeof(dp[cur]));            for (int k = 0; k < (1 << m); k ++) {                for (int p = 0; p <= d; p ++) {                    if (dp[1 - cur][k][p] == 0) continue;                    if (!map[i][j]) { //当前点不可放                        if ((k & (1 << (m - 1))) || (i >0 && map[i - 1][j] == 0)) {//上方已经有点是合法状态或者上方的点不可放置点                            int next = k << 1;                            add(dp[cur][next % (1 << m)][p], dp[1 - cur][k][p]);                        }                    }                    else//当前点可放                    {                        if (i > 0 && (k & (1 << (m - 1))) == 0 && map[i - 1][j] == 1) {                            //往上放1*2的,不在第一行,上面的点没放东西,并且上面的点可放.                            int next = ((k << 1) % (1 << m)) ^ 1;                            add(dp[cur][next][p], dp[1 - cur][k][p]);                        }                        if (j > 0 && (((k & (1 << (m - 1))) != 0) || (i > 0 && map[i - 1][j] == 0)) && map[i][j - 1] == 1 && (k & 1) == 0) {                            //往左放1*2的,不在第一列,上面的点已经放了东西或者不能放,左边的点没放东西并且可放                            int next = (((k << 1) % (1 << m)) ^ (3));                            add(dp[cur][next][p], dp[1 - cur][k][p]);                        }                        if ((((k & (1 << (m - 1))) != 0) || (i > 0 && map[i - 1][j] == 0)) && p < d) {                            //放1*1的,当前点上面已经放了或者不能放.                            int next = ((k << 1) % (1 << m)) ^ 1;                            add(dp[cur][next][p + 1], dp[1 - cur][k][p]);                        }                        if (((k & (1 << (m - 1))) != 0) || (i > 0 && map[i - 1][j] == 0)) {                            //当前点不放,当前点上面的点已经放了或者不能放.                            int next = ((k << 1) % (1 << m));                            add(dp[cur][next][p], dp[1 - cur][k][p]);                        }                    }                }            }        }    }    int ans = 0;    int tar = map[n - 1][0];    for (int i = 1; i < m; i ++) {        tar = 2 * tar + map[n - 1][i];    }    for (int i = c; i <= d; i ++) {        add(ans, dp[cur][tar][i]);    }    printf("%d\n", ans);}int main(){    char s[15];    while (scanf("%d%d%d%d", &n, &m, &c, &d) == 4) {        for (int i = 0; i < n; i ++) {            scanf("%s", s);            int len = (int)strlen(s);            for (int j = 0; j < len; j ++) {                map[i][j] = s[j] - '0';            }        }        cal_dp();    }    return 0;}


0 0
原创粉丝点击