【插头DP】URAL OJ 1519

本文介绍了一段使用C++进行代码优化的示例,通过多个#pragma GCC optimize指令增强了代码性能。同时,代码实现了一个迷宫问题的解决方案,通过遍历和状态更新寻找从起点到终点的路径,涉及位操作和二维数组处理。
摘要由CSDN通过智能技术生成
// #define KACHANG
#ifdef KACHANG
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#endif

#include <iostream>
#include <cstdio>
#include <cstring>

#define int long long

using namespace std;

int n, m;
const int N = (int) 4e4 + 10, M = (N << 1) + 7;
int g[20][N], q[2][N], cnt[N];
int h[2][M];
long long v[2][M];
int ex, ey;

inline int find(int cur, int x) {
    int t = x % M;
    while (h[cur][t] != -1 && h[cur][t] != x)
        if (++ t == M)
            t = 0;
    return t;
}

inline void insert(int cur, int state, int w) {
    int t = find(cur, state);
    if (h[cur][t] == -1) {
        h[cur][t] = state;
        v[cur][t] = w;
        q[cur][++ cnt[cur]] = t;
    }
    else
        v[cur][t] += w;
}

inline int get(int state, int k) {
    return state >> (k << 1) & 3;
}

inline int set(int k, int v) {
    return v * (1 << (k << 1));
}

signed main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) {
        char s[20];
        cin >> s + 1;
        for (int j = 1; j <= m; j ++)
            if (s[j] == '.') {
                g[i][j] = 1;
                ex = i, ey = j;
            }
    }
    
    long long res = 0;
    
    memset (h, -1, sizeof h);
    
    int cur = 0;
    
    insert(cur, 0, 1);
    
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= cnt[cur]; j ++)
            h[cur][q[cur][j]] <<= 2;
        for (int j = 1; j <= m; j ++) {
            int last = cur;
            cur ^= 1;
            cnt[cur] = 0;
            memset (h[cur], -1, sizeof h[cur]);
            for (int k = 1; k <= cnt[last]; k ++) {
                int state = h[last][q[last][k]];
                long long w = v[last][q[last][k]];
                int x = get(state, j - 1), y = get(state, j);
                if (! g[i][j]) {
                    if (! x && ! y)
                        insert(cur, state, w);
                }
                
                else if (! x && ! y) {
                    if (g[i + 1][j] && g[i][j + 1])
                        insert(cur, state + set(j - 1, 1) + set(j, 2), w);
                }
                
                else if (! x && y) {
                    if (g[i][j + 1])
                        insert(cur, state, w);
                    if (g[i + 1][j])
                        insert(cur, state + set(j - 1, y) - set(j, y), w);
                }
                
                else if (x && ! y) {
                    if (g[i][j + 1])
                        insert(cur, state - set(j - 1, x) + set(j, x), w);
                    if (g[i + 1][j])
                        insert(cur, state, w);
                }
                
                else if (x == 1 && y == 1) {
                    for (int u = j + 1, s = 1; ; u ++) {
                        int z = get(state, u);
                        if (z == 1)
                            s ++;
                        else if (z == 2)
                            if (-- s == 0) {
                                insert(cur, state - set(j - 1, x) - set(j, y) - set(u, 1), w);
                                break;
                            }
                    }
                }
                
                else if (x == 2 && y == 2) {
                    for (int u = j - 2, s = 1; ; u -- ) {
                        int z = get(state, u);
                        if (z == 2)
                            s ++;
                        else if (z == 1)
                            if (-- s == 0) {
                                insert(cur, state - set(j - 1, x) - set(j, y) + set(u, 1), w);
                                break;
                            }
                    }
                }

                else if (x == 2 && y == 1)
                    insert(cur, state - set(j - 1, x) - set(j, y), w);
                
                else if (i == ex && j == ey)
                    res += w;
            }
        }
    }
    
    cout << res << '\n';
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值