南京2013區域賽C題,HDU4804

**隊友用dfs過了,回來學了發輪廓線dp,現學現賣。
看過輪廓線後,覺得這玩意兒好神奇,寫起來比dfs順手多了,雖然兩者的思想其實都是差不多的,都是從一個合法狀態通過邊轉移到另一個狀態,dfs難寫,長,輪廓線好寫,容易寫錯。思路必須要清晰。
不說廢話了,輪廓線的經典之處在於每次枚舉舊的狀態。通過舊的狀態走到新狀態的時候,舊的狀態先左移一位,再建立新狀態,通過這樣移位的操作,就不用傻傻的在最內層循環通過dfs來搜狀態進行轉移了,直接位運算搞定。每次更新的都是第m-1位(假設行爲n,列爲m的話),
並且在m-1位上方的點就是(sta&(1<<m-1)) sta表示舊狀態,在m-1左邊一個位置的點就是第0位,具體看代碼轉移**
//
//  Created by Running Photon on
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e2 + 10;
const int maxv = 1e1 + 10;
const double eps = 1e-9;

int n, m, c, d;
int mp[maxn][maxv];
int state[maxn];
int cur;
ll dp[2][(1 << 10) + 10][25];
void update(int a, int b, int c, int d) {
    if(b & (1 << m)) dp[cur][b^(1<<m)][c] = (dp[cur][b^(1<<m)][c] + dp[1-cur][a][d]) % MOD;
}
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    while(scanf("%d%d%d%d", &n, &m, &c, &d) != EOF) {
        CLR(state); CLR(dp);
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                scanf("%1d", mp[i] + j);
                mp[i][j] ^= 1;
                state[i] = state[i] * 2 + mp[i][j];
            }
        }
//        for(int i = 0; i < n; i++) {
//            for(int j = 0; j < m; j++) {
//                printf("%d ", mp[i][j]);
//            }
//            puts("");
//        }
        dp[0][(1 << m) - 1][0] = 1;
        cur = 0;
//        int flag = 0;
//        for(int i = 0; i < n; i++){
//            if(state[i] != (1 << m) - 1) flag = 1;
//        }
//        if(!flag) {puts("0"); continue;}
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                cur ^= 1;
                CLR(dp[cur]);
                for(int sta = 0; sta < (1 << m); sta++) {
                    for(int k = 0; k <= d; k++) {
                        if(mp[i][j]) {
                            update(sta, (sta << 1) ^ 1, k, k);
                            continue;
                        }
                        update(sta, sta << 1, k, k);
                        if(k != d)
                            update(sta, (sta << 1) ^ 1, k+1, k);
                        if(i && !(sta & (1 << m - 1)))
                            update(sta, (sta << 1) ^ (1 << m) ^ 1, k, k);
                        if(j && !mp[i][j-1] && !(sta & 1))
                            update(sta, (sta << 1) ^ 3, k, k);
                    }
                }
            }
        }
        ll ans = 0;
        for(int i = c; i <= d; i++) {
            ans = (ans + dp[cur][(1 << m) - 1][i]) % MOD;
        }
        printf("%lld\n", ans);
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章