当前位置:   article > 正文

洛谷 P5056 【模板】插头dp_洛谷p5056

洛谷p5056
题目链接
题意

给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路。问有多少种铺法?

思路

比赛时基本做不出来,就学个新算法玩玩。

学习链接

代码对于我这个不会hash_table 的不太友好,先自己封装了一个用着舒服的hash_table,当然也可以直接用STL里的 unordered_map,初学算法我认为直接使用后者更好,循序渐进。

插头dp简单的说还是轮廓线的状压dp?,多考虑了一种连通性问题。
用括号表示法表示轮廓线后,然后考虑状态转移。
枚举每点,考虑左边的朝右插头 r,上边朝下插头 d,左插头1表示,右插头2表示

  • if 当前点是障碍
  • else if (!r && !d)
  • else if (r && !d)
  • else if (!r && d)
  • else if (r == 1 && d == 1)
  • else if (r == 2 && d == 2)
  • else if (r == 1 && d == 2)
  • else if (r == 2 && d == 1)

所有的情况就这么多,然后每点考虑插头形状转移即可

一个坑点 | ^ 运算符优先级不同,不是从左到右运算,然后找了半天bug,还是用 + - 比较稳。

代码

STL unordered_map
代码
991ms
吸氧后 228ms

#include <bits/stdc++.h>
using namespace std;

#define ll long long

unordered_map<ll,ll> dp[3];
// chatou 0 null, 1 right, 2 down
ll n, m, endx, endy, a[15][15], bit[15];
#define prel (1ll<<bit[j-1])
#define prer (1ll<<bit[j])

void solve() {
    ll cur = 0, ans = 0;
    dp[cur].clear();
    dp[0][0] = 1;
    for(ll i = 1; i <= n; ++i) {
        dp[2].clear();
        for(auto j : dp[cur]) dp[2][j.first<<2] = j.second;
        dp[cur] = dp[2];
        for(ll j = 1; j <= m; ++j) {
            cur ^= 1;
            dp[cur].clear();
            for(auto k : dp[cur^1]) {
                ll sta = k.first;
                ll w = k.second;
                ll d = (sta>>bit[j])&3ll;
                ll r = (sta>>bit[j-1])&3ll;
//                    printf("%lld %lld - %lld %lld\n",i,j,sta,w);
//                    printf("%lld = %lld\n\n",r,d);
                if(!a[i][j]) {
                    if(!r && !d) dp[cur][sta] += w;
                }
                else if(!r && !d) {
                    if(a[i+1][j] && a[i][j+1]) dp[cur][sta + prel + (2*prer)] += w;
                }
                else if(r && !d) {
                    if(a[i+1][j]) dp[cur][sta] += w;
                    if(a[i][j+1]) dp[cur][sta - (r*prel) + (r*prer)] += w;
                }
                else if(!r && d) {
                    if(a[i+1][j]) dp[cur][sta + (d*prel) - (d*prer)] += w;
                    if(a[i][j+1]) dp[cur][sta] += w;
                }
                else if(r == 1 && d == 1) {
                    ll cnt = 1;
                    for(ll p = j+1; p <= m; ++p) {
                        if(((sta>>bit[p])&3ll) == 1) ++cnt;
                        if(((sta>>bit[p])&3ll) == 2) --cnt;
                        if(!cnt) {
                            dp[cur][(sta - (r*prel) - (d*prer)) - (1<<bit[p])] += w;
                            break;
                        }
                    }
                }
                else if(r == 2 && d == 2) {
                    ll cnt = 1;
                    for(ll p = j-2; p >= 0; --p) {
                        if(((sta>>bit[p])&3ll) == 1) --cnt;
                        if(((sta>>bit[p])&3ll) == 2) ++cnt;
                        if(!cnt) {
                            dp[cur][(sta - (r*prel) - (d*prer)) + (1<<bit[p])] += w;
                            break;
                        }
                    }
                }
                else if(r == 2 && d == 1) {
                    dp[cur][sta - (r*prel) - (d*prer)] += w;
                }
                else if(r == 1 && d == 2) { // ok
                    if(i == endx && j == endy) ans += w;
                }
            }
        }
    }
    printf("%lld\n",ans);
}

int main() {
    scanf("%lld%lld",&n,&m);
    for(ll i = 1; i <= n; ++i) {
        char s[15];
        scanf("%s",s+1);
        for(ll j = 1; j <= m; ++j) {
            if(s[j] == '.') {
                a[i][j] = 1;
                endx = i;
                endy = j;
            }
        }
    }
    for(ll i = 1; i <= 13; ++i) bit[i] = i<<1;
    solve();
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

手写hash_table
代码
577ms
吸氧后 562ms

#include <bits/stdc++.h>
using namespace std;

#define ll long long

struct hash_table {
    ll hash_mod = 590027;
    ll state[600000], ans[600000], up;
    ll tot, first[600000], nxt[600000], w[600000];
    void init() {
        memset(first, 0, sizeof(first));
        tot = 0;
        up = 0;
    }
    ll ins(ll sta, ll val) {
        ll key = sta%hash_mod;
        for(ll i = first[key]; i; i = nxt[i]) {
            if(state[w[i]] == sta) return ans[w[i]] += val;
        }
        state[++up] = sta;
        ans[up] = val;
        nxt[++tot] = first[key];
        w[tot] = up;
        first[key] = tot;
        return val;
    }
}dp[2];

/*hash_table*/
// chatou 0 null, 1 right, 2 down
ll n, m, endx, endy, a[15][15], bit[15];
#define prel (1ll<<bit[j-1])
#define prer (1ll<<bit[j])

void solve() {
    ll cur = 0, ans = 0;
    dp[cur].init();
    dp[0].ins(0,1);
    for(ll i = 1; i <= n; ++i) {
        for(ll j = 1; j <= dp[cur].up; ++j) dp[cur].state[j] <<= 2;
        for(ll j = 1; j <= m; ++j) {
            cur ^= 1;
            dp[cur].init();
            for(ll k = 1; k <= dp[cur^1].up; ++k) {
                ll sta = dp[cur^1].state[k];
                ll w = dp[cur^1].ans[k];
                ll d = (sta>>bit[j])&3ll;
                ll r = (sta>>bit[j-1])&3ll;
//                    printf("%lld %lld - %lld %lld\n",i,j,sta,w);
//                    printf("%lld = %lld\n\n",r,d);
                if(!a[i][j]) {
                    if(!r && !d) dp[cur].ins(sta,w);
                }
                else if(!r && !d) {
                    if(a[i+1][j] && a[i][j+1]) dp[cur].ins(sta + prel + (2*prer),w);
                }
                else if(r && !d) {
                    if(a[i+1][j]) dp[cur].ins(sta,w);
                    if(a[i][j+1]) dp[cur].ins(sta - (r*prel) + (r*prer),w);
                }
                else if(!r && d) {
                    if(a[i+1][j]) dp[cur].ins(sta + (d*prel) - (d*prer),w);
                    if(a[i][j+1]) dp[cur].ins(sta,w);
                }
                else if(r == 1 && d == 1) {
                    ll cnt = 1;
                    for(ll p = j+1; p <= m; ++p) {
                        if(((sta>>bit[p])&3ll) == 1) ++cnt;
                        if(((sta>>bit[p])&3ll) == 2) --cnt;
                        if(!cnt) {
                            dp[cur].ins((sta - (r*prel) - (d*prer)) - (1<<bit[p]),w);
                            break;
                        }
                    }
                }
                else if(r == 2 && d == 2) {
                    ll cnt = 1;
                    for(ll p = j-2; p >= 0; --p) {
                        if(((sta>>bit[p])&3ll) == 1) --cnt;
                        if(((sta>>bit[p])&3ll) == 2) ++cnt;
                        if(!cnt) {
                            dp[cur].ins((sta - (r*prel) - (d*prer)) + (1<<bit[p]),w);
                            break;
                        }
                    }
                }
                else if(r == 2 && d == 1) {
                    dp[cur].ins(sta - (r*prel) - (d*prer),w);
                }
                else if(r == 1 && d == 2) { // ok
                    if(i == endx && j == endy) ans += w;
                }
            }
        }
    }
    printf("%lld\n",ans);
}

int main() {
    scanf("%lld%lld",&n,&m);
    for(ll i = 1; i <= n; ++i) {
        char s[15];
        scanf("%s",s+1);
        for(ll j = 1; j <= m; ++j) {
            if(s[j] == '.') {
                a[i][j] = 1;
                endx = i;
                endy = j;
            }
        }
    }
    for(ll i = 1; i <= 13; ++i) bit[i] = i<<1;
    solve();
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/50903
推荐阅读
相关标签
  

闽ICP备14008679号