• Ural 1519. Formula 1 优美的插头DP


    今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的,由于要考虑好多东西,而且昨晚2点睡的有点困,最后终于磨蹭出来了,第一次的代码搓没关系,自己写的才重要。然后果然不出我所料,调试到了晚上才A了(一个郁闷的错误)。。。A的感觉真的是爽呀,虽然搞了差不多一天。当然自己写了自己想的代码后也要把代码优化,不然队友看不懂自己代码就囧了。。。


    插头DP,建议大家想学的好好看看陈丹琦的国家集训队论文,这是个优美的DP。

    http://www.docin.com/p-46797997.html


     

    #include <stdio.h>
    #include <string.h>
    
    #define LL __int64
    
    const int mod = 10007;
    
    //   哈希表
    struct HASH{
        int head[mod+10], E, next[80000];
        LL val[80000], cnt[80000];
    
        void init() {
            memset(head, -1, sizeof(head));
            E = 0;
        }
    
        int findhash(LL x) {
            return (x%mod + mod)%mod;
        }
    
        void add(LL x, LL sum) {
            int u = findhash(x);
            for(int i = head[u];i != -1;i = next[i]) if(val[i] == x) {
                cnt[i] += sum;
                return ;
            }
            val[E] = x;
            cnt[E] = sum;
            next[E] = head[u];
            head[u] = E++;
        }
    
    }biao1, biao2;
    
    int c[22], n, m, d[22];
    //  编码
    void get(LL x) {
        for(int i = m+1;i >= 1; i--) {
            c[i] = x&7;
            x /= 8;
        }
    }
    //  解码
    LL getval() {
        LL ret = 0;
        for(int i = 1;i <= m+1; i++) {
            ret |= d[i];
            ret *= 8;
        }
        ret /= 8;
        return ret ;
    }
    //   转化成最小表示法
    void change() {
        int vis[22];
        memset(vis, 0, sizeof(vis));
        int num = 1;
        for(int i = 1;i <= m+1;i ++) {
            if(!d[i])   continue;
            if(!vis[d[i]]) {
                vis[d[i]] = num;
                d[i] = num++;
            }
            else {
                d[i] = vis[d[i]];
            }
        }
    }
    
    void fuzhi() {
        for(int i = 1;i <= m+1;i ++)    d[i] = c[i];
    }
    
    char s[22][22];
    
    int main() {
        int i, j, k, l;
        while(scanf("%d%d", &n, &m) != -1) {
            for(i = 1;i <= n; i++)
                scanf("%s", s[i]+1);
            int tot = 0;
            for(i = 1;i <= n; i++)
                for(j = 1;j <= m; j++)
                if(s[i][j] == '.')  tot++;
            if(tot%2==1 || tot < 4) {
                puts("0");
                continue;
            }
            int tox  = -1, toy = -1;
            for(i = 1;i <= n; i++)
            for(j = 1;j <= m; j++) if(s[i][j] == '.') {
                tox = i;
                toy = j;
            }
            biao1.init();
            biao1.add(0, 1);
            LL ans = 0;
            for(i = 1;i <= n; i++){
                for(j = 0;j <= m; j++){
                    biao2.init();
                    for(l = 0;l < biao1.E; l++)  {
                        get(biao1.val[l]);
                        if(j == m) {
                            for(int ii = 2;ii <= m+1; ii++) d[ii] = c[ii-1];
                            d[1] = 0;
                            change();
                            LL now = getval();
                            biao2.add(now, biao1.cnt[l]);
                            continue;
                        }
                        if(c[j+1] && !c[j+2]) {  //  有左插头无上插头
                            if(s[i][j+1] != '.')  continue;
                            if(j+2 <= m) {
                                fuzhi();
                                d[j+1] = 0;d[j+2] = c[j+1];
                                change();
                                LL now = getval();
                                biao2.add(now, biao1.cnt[l]);
                            }
                            if(i < n) {
                                fuzhi();
                                change();
                                LL now = getval();
                                biao2.add(now, biao1.cnt[l]);
                            }
                        }
                        else if(!c[j+1] && c[j+2]) {  //  有上插头无左插头
                            if(s[i][j+1] != '.')  continue;
                            if(i < n) {
                                fuzhi();
                                d[j+1] = c[j+2]; d[j+2] = 0;
                                change();
                                LL now = getval();
                                biao2.add(now, biao1.cnt[l]);
                            }
                            if(j+2 <= m) {
                                fuzhi();
                                change();
                                LL now = getval();
                                biao2.add(now, biao1.cnt[l]);
                            }
                        }
                        else if(!c[j+1] && !c[j+2]) { //   左和上都无插头
                            if(s[i][j+1] != '.') {
                                fuzhi();
                                change();
                                LL now = getval();
                                biao2.add(now, biao1.cnt[l]);
                                continue;
                            }
                            if(j+2 <= m && i < n) {
                                fuzhi();
                                d[j+1] = d[j+2] = 13;
                                change();
                                LL now = getval();
                                biao2.add(now, biao1.cnt[l]);
                            }
                        }
                        else { //  左和上都有插头 ,  要判断左和上插头是否连通
                            if(c[j+2] == c[j+1]) {
                                int tot = 0;
                                for(int ii = 1;ii <= m+1; ii++) if(c[ii])
                                    tot++;
                                if(tot == 2 && i == tox && j+1 == toy) ans += biao1.cnt[l];
                            }
                            else {
                                if(s[i][j+1] != '.')    continue;
                                fuzhi();
                                for(int ii = 1;ii <= m+1; ii++) if(ii != j+1 && ii != j+2 && d[ii] == d[j+1]) {
                                    d[ii] = d[j+2];
                                    break;
                                }
                                d[j+1] = d[j+2] = 0;
                                change();
                                LL now = getval();
                                biao2.add(now, biao1.cnt[l]);
                            }
                        }
                    }
                    biao1 = biao2;
                }
            }
            printf("%I64d
    ", ans);
        }
        return 0;
    }
    



  • 相关阅读:
    D. Almost All Divisors
    G
    K
    L3-016 二叉搜索树的结构 (30 分)
    D. Colored Boots(STL)
    O
    [论文]Clustering-Based Ensembles as an Alternative to Stacking
    [LeetCode] Factorial Trailing Zeroes 阶乘末尾0
    [LeetCode] Maximum Depth of Binary Tree dfs,深度搜索
    [LeetCode] Count and Say 字符串
  • 原文地址:https://www.cnblogs.com/riskyer/p/3235281.html
Copyright © 2020-2023  润新知