• Google Code Jam 2020 Round 1A 2020 题解


    Problem A. Pattern Matching
    把每个字符串分成第一个之前,最后一个之后,中间的部分 三个部分
    每个字符串的中间的部分可以直接拼接
    前后两个部分需要判断下是否合法

    #include <algorithm>
    #include <bitset>
    #include <cassert>
    #include <cmath>
    #include <complex>
    #include <cstring>
    #include <ctime>
    #include <deque>
    #include <fstream>
    #include <functional>
    #include <iomanip>
    #include <iostream>
    #include <map>
    #include <numeric>
    #include <queue>
    #include <random>
    #include <set>
    #include <stack>
    #include <unordered_map>
    #include <unordered_set>
    #include <vector>
    #define MP make_pair
    #define ll long long
    #define ld long double
    #define null NULL
    #define all(a) a.begin(), a.last()
    #define forn(i, n) for (int i = 0; i < n; ++i)
    #define sz(a) (int)a.size()
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    #define bitCount(a)  __builtin_popcount(a)
    template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
    template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
    using namespace std;
    const int INF = 0x3f3f3f3f;
    string to_string(string s) { return '"' + s + '"'; }
    string to_string(const char* s) { return to_string((string) s); }
    string to_string(bool b) { return (b ? "true" : "false"); }
    template <typename A, typename B>
    string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
    template <typename A>
    string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
    void debug_out() { cerr << endl; }
    template <typename Head, typename... Tail>
    void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
    #ifdef LOCAL
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
    #else
    #define debug(...) 42
    #endif
    
    char seq[55][105];
    
    int main() {
        int T;
        scanf("%d", &T);
        for(int cas = 1; cas <= T; ++cas) {
            int n;
            scanf("%d", &n);
            for(int i = 0; i < n; ++i) {
                scanf("%s", seq[i]);
            }
    
            vector<string> front, last;
            string mid_result;
            for(int i = 0; i < n; ++i) {
                int len = strlen(seq[i]);
                vector<string> split;
                string tmp;
                if(seq[i][0] == '*') split.push_back("");
                for(int j = 0; j < len; ++j) {
                    // cout << seq[i][j] << endl;
                    if(seq[i][j] == '*') { 
                        if((int)tmp.size() != 0) split.push_back(tmp);
                        tmp.clear();
                    } else tmp += seq[i][j];
                }
                if((int)tmp.size() != 0) split.push_back(tmp);
                // debug(split);
                if(seq[i][len - 1] == '*') split.push_back("");
    
                front.push_back(split[0]); last.push_back(split.back());
                if(split.size() > 2) {
                    for(int j = 1, split_len = split.size(); j < split_len - 1; ++j) {
                        mid_result += split[j];
                    }
                } 
            }
    
            auto cmp = [](string &A, string &B) { return A.size() < B.size(); };
            sort(front.begin(), front.end(), cmp);
            sort(last.begin(), last.end(), cmp);
    
            // debug(front, last, mid_result);
    
            bool suc = true;
    
            for(int i = 0, len = front.size(); i < len - 1 && suc; ++i) {
                string &now = front[i]; string &tem = front.back();
                for(int j = 0, len_now = now.size(); j < len_now && suc; ++j) {
                    if(now[j] != tem[j]) { suc = false; }
                }
            }
    
            // debug(suc);
    
            for(int i = 0, len = last.size(); i < len - 1 && suc; ++i) {
                string &now = last[i]; string &tem = last.back(); int len_tem = tem.size();
                for(int j = 0, len_now = now.size(); j < len_now && suc; ++j) {
                    if(now[j] != tem[len_tem + j - len_now]) { 
                        // debug(now, tem, j); 
                        suc = false; 
                    }
                }
            }
    
            string result = front.back() + mid_result + last.back();
    
            printf("Case #%d: ", cas);
            if(suc == false) printf("*
    ");
            else printf("%s
    ", result.c_str());
        }
        return 0;
    }
    
    /*
    
    
    2
    5
    *CONUTS
    *COCONUTS
    *OCONUTS
    *CONUTS
    *S
    2
    *XZ
    *XYZ
    
    
    */
    

    problem B. Pascal Walk
    这是一个 非常巧妙的构造题
    首先想到一个杨辉三角的每一个层的和是 2^i ,如果我们可以跳跃就好了,直接按照N的二进制表示,使用对应层的和
    问题在于我们无法跳跃,怎么办
    通过构造可以发现我们可以将两个很远的两层连在一起,下面举例5,19的情况,具体的逻辑可以去代码里面体会

    #include <algorithm>
    #include <bitset>
    #include <cassert>
    #include <cmath>
    #include <complex>
    #include <cstring>
    #include <ctime>
    #include <deque>
    #include <fstream>
    #include <functional>
    #include <iomanip>
    #include <iostream>
    #include <map>
    #include <numeric>
    #include <queue>
    #include <random>
    #include <set>
    #include <stack>
    #include <unordered_map>
    #include <unordered_set>
    #include <vector>
    #define MP make_pair
    #define ll long long
    #define ld long double
    #define null NULL
    #define all(a) a.begin(), a.last()
    #define forn(i, n) for (int i = 0; i < n; ++i)
    #define sz(a) (int)a.size()
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    #define bitCount(a)  __builtin_popcount(a)
    template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
    template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
    using namespace std;
    const int INF = 0x3f3f3f3f;
    string to_string(string s) { return '"' + s + '"'; }
    string to_string(const char* s) { return to_string((string) s); }
    string to_string(bool b) { return (b ? "true" : "false"); }
    template <typename A, typename B>
    string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
    template <typename A>
    string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
    void debug_out() { cerr << endl; }
    template <typename Head, typename... Tail>
    void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
    #ifdef LOCAL
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
    #else
    #define debug(...) 42
    #endif
    
    void add(vector<pair<int, int> >& vc, int pre, int target, int times) {
        // debug(pre, target, vc);
        int dir = 0;
        if( times % 2 == 0) dir = 0; else dir = 1;
        int preX = -1, preY = 0;
        if(vc.size() != 0) {
            preX = vc.back().first; preY = vc.back().second;
        }
    
    
        int needFloor = target - pre - 1;
        if(needFloor == 0) {
            vc.push_back(dir ? MP(preX + 1, preY + 1) : MP(preX + 1, preY));
            for(int i = 0; i < target; ++i) {
                vc.push_back(dir ? MP(vc.back().first, vc.back().second - 1) : MP(vc.back().first, vc.back().second + 1));
            }
        } else {
            vc.push_back(dir ? MP(preX + 1, preY + 1) : MP(preX + 1, preY));
            int count = 2;
            for(int i = 0; i < needFloor - 1; ++i) {
                int tmp_count = count - 1; int now_dir = (i & 1) ^ (needFloor & 1) ^ dir;
                vc.push_back(now_dir ? MP(vc.back().first + 1, vc.back().second + 1) : MP(vc.back().first + 1, vc.back().second));
                while(tmp_count --) {
                    vc.push_back(now_dir ? MP(vc.back().first, vc.back().second - 1) : MP(vc.back().first, vc.back().second + 1));
                }   
                count ++;
            }
            vc.push_back(dir ? MP(vc.back().first + 1, vc.back().second) : MP(vc.back().first + 1, vc.back().second + 1));
            for(int i = 0; i < target - count + 1; ++i) {
                vc.push_back(dir ? MP(vc.back().first, vc.back().second - 1) : MP(vc.back().first, vc.back().second + 1));
            }
        }
    
    }
    
    
    
    int main() {
        int T;
        scanf("%d", &T);
        for(int cas = 1; cas <= T; ++cas) {
            int n;
            scanf("%d", &n);
    
            vector<pair<int, int> > vc;
    
            int floor = -1; int cnt = 0; int times = 0;
            while(n) {
                if(n & 1) {
                    add(vc, floor, cnt, times);
                    times ++;
                    floor = cnt;
                }
                cnt ++;
                n /= 2;
            }
            assert((int)vc.size() < 500);
            printf("Case #%d: 
    ", cas);
            for(int i = 0, len = vc.size(); i < len; ++i) {
                printf("%d %d
    ", vc[i].first + 1, vc[i].second + 1);
            }
        }
        return 0;
    }
    

    Problem C: Square Dance
    这题看起来就是暴力,能过小数据
    有个显而易见的优化,就是每次删除一个点之后,下一轮潜在的可能删除点一定是上轮被删点的邻居
    复杂度不太会算,题解说这样优化后能到O(R * C)
    找邻居这种数据结构 我用十字链表维护的

    #include <algorithm>
    #include <bitset>
    #include <cassert>
    #include <cmath>
    #include <complex>
    #include <cstring>
    #include <ctime>
    #include <deque>
    #include <fstream>
    #include <functional>
    #include <iomanip>
    #include <iostream>
    #include <map>
    #include <numeric>
    #include <queue>
    #include <random>
    #include <set>
    #include <stack>
    #include <unordered_map>
    #include <unordered_set>
    #include <vector>
    #define MP make_pair
    #define ll long long
    #define ld long double
    #define null NULL
    #define all(a) a.begin(), a.last()
    #define forn(i, n) for (int i = 0; i < n; ++i)
    #define sz(a) (int)a.size()
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    #define bitCount(a)  __builtin_popcount(a)
    template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
    template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
    using namespace std;
    const int INF = 0x3f3f3f3f;
    string to_string(string s) { return '"' + s + '"'; }
    string to_string(const char* s) { return to_string((string) s); }
    string to_string(bool b) { return (b ? "true" : "false"); }
    template <typename A, typename B>
    string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
    template <typename A>
    string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
    void debug_out() { cerr << endl; }
    template <typename Head, typename... Tail>
    void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
    #ifdef LOCAL
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
    #else
    #define debug(...) 42
    #endif
    
    
    struct Node{
        int u, d, l, r;
        int val;
        Node() {
            u = d = l = r = -1; val = 0;
        }
    };
    vector<Node> mp;
    int R, C;
    
    int getId(int x, int y) { return x * (C + 2) + y; }
    
    void erase(int x) {
       mp[mp[x].l].r = mp[x].r;
       mp[mp[x].r].l = mp[x].l;
       mp[mp[x].u].d = mp[x].d;
       mp[mp[x].d].u = mp[x].u;
       mp[x].val = 0;
    }
    
    
    vector<int> update(vector<int> &choosList, ll &ans, ll &origin) {
        // debug(origin);
        
        vector<int> needErase;
        vector<int> newList, _newList;
        ans += origin;
        for(int i = 0, len = choosList.size(); i < len; ++i) {
            int x = choosList[i];
            int neiNum = 0; int neiVal = 0; 
            if(mp[mp[x].r].val != 0) { neiNum ++; neiVal += mp[mp[x].r].val; }
            if(mp[mp[x].l].val != 0) { neiNum ++; neiVal += mp[mp[x].l].val; }
            if(mp[mp[x].u].val != 0) { neiNum ++; neiVal += mp[mp[x].u].val; }
            if(mp[mp[x].d].val != 0) { neiNum ++; neiVal += mp[mp[x].d].val; }
            
            // debug(x / (C + 2), x % (C + 2), neiVal, neiNum, mp[x].val);
            if(neiVal > mp[x].val * neiNum) { 
                // debug("erase", x / (C + 2), x % (C + 2));
                origin -= mp[x].val; 
                needErase.push_back(x);
                
            }
        }
        
        for(auto x : needErase) {
            assert(mp[x].r != -1); assert(mp[x].l != -1); assert(mp[x].u != -1); assert(mp[x].d != -1);
            if(mp[mp[x].r].val != 0) { _newList.push_back(mp[x].r); }
            if(mp[mp[x].l].val != 0) { _newList.push_back(mp[x].l); }
            if(mp[mp[x].u].val != 0) { _newList.push_back(mp[x].u); }
            if(mp[mp[x].d].val != 0) { _newList.push_back(mp[x].d); }
            erase(x);
        }
    
        for(auto it : _newList) {
            if(mp[it].val != 0) newList.push_back(it);
        }
        sort(newList.begin(), newList.end());
        newList.erase(unique(newList.begin(), newList.end()), newList.end());
        
        // for(int i = 0, len = newList.size(); i < len; ++i) printf("%d %d: ", newList[i] / (C + 2), newList[i] % (C + 2)); printf("
    ");
    
        return newList;
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        for(int cas = 1; cas <= T; ++cas) {
            mp.clear();
            scanf("%d %d", &R, &C);
            mp.resize( (R + 5) * (C + 5), Node());
    
            ll origin = 0;
            for(int i = 1; i <= R; ++i) {
                for(int j = 1; j <= C; ++j) {
                    scanf("%d", &mp[getId(i , j)].val);
                    origin += mp[getId(i , j)].val;
                }
            }
    
            for(int i = 1; i <= R; ++i) {
                mp[getId(i , 1)].l = getId(i, 0);
                for(int j = 1; j <= C; ++j) {
                    mp[getId(i , j - 1)].r = getId(i, j);
                    mp[getId(i , j + 1)].l = getId(i, j);
                }
                mp[getId(i , C)].r = getId(i, C + 1);
            }
            
            for(int i = 1; i <= C; ++i) {
                mp[getId(1 , i)].u = getId(0, i);
                for(int j = 1; j <= R; ++j) {
                    mp[getId(j - 1, i)].d = getId(j, i);
                    mp[getId(j + 1, i)].u = getId(j, i);
                }
                mp[getId(R, i)].d = getId(R + 1, i);
            }
            
            vector<int> choosList;
            for(int i = 1; i <= R; ++i) {
                for(int j = 1; j <= C; ++j) {
                    choosList.push_back(getId(i, j));
                }
            }
    
            
    
            ll ans = 0;
            while(1) {
                choosList = update(choosList, ans, origin);
                if(choosList.size() == 0) break;
            }
    
            printf("Case #%d: %lld
    ", cas, ans);
    
        }
        return 0;
    }
    
    /*
    
    
    4
    1 1
    15
    3 3
    1 1 1
    1 2 1
    1 1 1
    1 3
    3 1 2
    1 3
    1 2 3
    
    
    3 3
    1 100 1
    1 2 2
    1000 1 1
    1 3
    1 1
    */
    
  • 相关阅读:
    关于fragment点击能穿透问题
    Eclipse的PHP插件PHPEclipse安装和使用
    Eclipse的PHP插件PHPEclipse安装和使用
    解决在极光推送的时候会出现一个 JPush提示:缺少统计代码
    解决在极光推送的时候会出现一个 JPush提示:缺少统计代码
    Spring学习总结(17)——Spring AOP权限管理
    Gradle学习总结——抓重点学Gradle
    WebService学习总结(6)——WebService常用接口
    Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源
    Spring学习总结(15)——Spring AOP 拦截器的基本实现
  • 原文地址:https://www.cnblogs.com/Basasuya/p/12684566.html
Copyright © 2020-2023  润新知