[hdu4285 circuits] 插头dp

来源:互联网 发布:绝地求生n卡优化 编辑:程序博客网 时间:2024/04/29 21:03

题意:一个n*m的01矩阵,用刚好k个回路覆盖所有的1,回路之间不能相互包含、交叉,求方法总数。
思路:又1个回路问题,与单回路和多回路问题不同,这题限制了回路个数,那么把回路个数加进状态里面,在转移的时候维护下即可。具体来说,采用8进制表示连通性,用最小表示法将状态编码,dp时用hash保存一个阶段的所有状态。

#include <bits/stdc++.h>using namespace std;#ifndef ONLINE_JUDGE#include "local.h"#endif // ONLINE_JUDGE#define pb(x)                   push_back(x)#define mp(x, y)                make_pair(x, y)#define all(a)                  (a).begin(), (a).end()#define mset(a, x)              memset(a, x, sizeof(a))#define mcpy(a, b)              memcpy(a, b, sizeof(b))#define up(a, b)                for (int a = 0; a < (b); a ++)#define down(a, b)              for (int a = b - 1; (a) >= 0; a --)#define rep(i, a, b)            for (int i = a; i <= (b); i ++)#define rrep(i, a, b)           for (int i = a; i >= (b); i --)#define cas()                   int T, cas = 0; cin >> T; while (T --)#define printCas(ch)            printf("Case #%d:%c", ++ cas, ch)#define watch(ele)              cout << ele << endl;#define in(a)                   scanf("%d", &a)typedef long long ll;typedef pair<int, int> pii;template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}const int mod = 1e9 + 7;const int N = 15007;struct HashMap {    int head[N];    ll key[N];    int value[N][40];    int nxt[N];    int sz;    HashMap() {clear();}    void clear() {        sz = 0;        mset(head, -1);        mset(value, 0);    }    int push(ll state, int c, int val) {        int pos = state % N, i = head[pos];        for (; ~i; i = nxt[i]) {            if (key[i] == state) {                value[i][c] += val;                if (value[i][c] >= mod) value[i][c] -= mod;                return i;            }        }        if (i == -1) {            value[sz][c] = val;            key[sz] = state;            nxt[sz] = head[pos];            head[pos] = sz ++;            return sz - 1;        }    }};HashMap dp[2];int code[15], code2[15];char used[10], id[10];int n, m, K, c, row, col, newk, maxid, val, cur;ll ans;char s[22][22];ll encode(int a[]) {    ans = 0;    rrep(i, m, 0) {        ans = ans << 3 | a[i];    }    return ans;}void decode(int a[], ll state) {    rep(i, 0, m) {        a[i] = state & 7;        state >>= 3;    }}bool chk() {    c = 0;    rep(i, 0, col - 1) rep(j, col + 1, m - 1) {        if (code[i] && code[i] == code[j]) c ^= 1;    }    return c == 0;}void relax() {    mset(used, 1);    c = 1;    rep(i, 0, m) {        if (code2[i] && used[code2[i]]) id[code2[i]] = c ++;        used[code2[i]] = 0;    }    rep(i, 0, m) code2[i] = id[code2[i]];}void merge() {    up(i, m) {        if (i != col && code[i] == code[col]) code2[i] = code[m];    }    code2[m] = code2[col] = 0;    if (code[m] == code[col]) newk ++;    relax();}void turn() {    code2[m] = code[col];    code2[col] = code[m];    relax();}void create() {    maxid = 0;    up(i, m) umax(maxid, code[i]);    code2[m] = code2[col] = maxid + 1;    relax();}#define update() dp[cur ^ 1].push(encode(code2), newk, val)void trans() {    if (s[row][col] == '*' && (code[m] || code[col])) return;    if (col == 0 && code[m]) return;    if (code[m] && code[col]) {        if (code[m] == code[col]) {            if (chk()) {                merge();                update();            }        }        else {            merge();            update();        }    }    if (code[m] && !code[col] || !code[m] && code[col]) {        update();        turn();        update();    }    if (!code[m] && !code[col]) {        if (s[row][col] == '*') update();        else {            create();            update();        }    }}int work() {    if (K > n * m / 4) return 0;    cur = 0;    dp[0].clear();    dp[1].clear();    dp[0].push(0, 0, 1);    up(i, n) up(j, m) {        up(k, dp[cur].sz) up(p, K + 1) {            decode(code, dp[cur].key[k]);            memcpy(code2, code, sizeof(code2));            newk = p;            val = dp[cur].value[k][p];            row = i;            col = j;            if (val) trans();        }        dp[cur].clear();        cur ^= 1;    }    return dp[cur].value[dp[cur].push(0, K, 0)][K];}int main() {#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);    //freopen("out.txt", "w", stdout);#endif // ONLINE_JUDGE    cas() {        cin >> n >> m >> K;        up(i, n) scanf("%s", s[i]);        cout << work() << endl;    }    return 0;}
0 0
原创粉丝点击