Google Code Jam 2015 QR

本文深入探讨了算法实现和具体技术应用,包括但不限于Dijkstra算法优化、Ominous Omino问题解决策略、字符操作与字符串处理技巧。文章详细阐述了解决方案、核心逻辑与优化方法,旨在为读者提供深入理解与实际应用的指南。

牛人自有牛人的做法,弱渣也有弱渣的做法。。。分享一下。。

Problem C. Dijkstra

因为ijk = -1

那么我们只需要找prefix的i和suffix的k即可。

而发现一共就4种运算符,所以最多8位一个循环,那么我就if X > 20 then X = 20

重载了一下运算符号,这样就能避免很多不必要的麻烦写法

昂神教我的,既然是乘法那么正负符号分开算好了。。

char str[1000000];
string L , a;
LL n , x;
int c[][4] =  { {0 , 1 , 2 , 3},
               {1 , 0 , 3 , 2},
               {2 , 3 , 0 , 1},
               {3 , 2 , 1 , 0}};
int neg[][4] = {{1 , 1 , 1 , 1},
               {1 ,-1 , 1 ,-1},
               {1 ,-1 ,-1 , 1},
               {1 , 1 ,-1 ,-1}};
int f(char c){
    if (c == 'i') return 1;
    if (c == 'j') return 2;
    return 3;
}
struct Number{
    int ele , op;
    void ONE(){
        ele = 0;
        op = 1;
    }
    Number(){}
    Number(int c){
        ele = c;
        op = 1;
    }
    Number operator * (const Number & A) const{
        Number ret;
        ret.op = op * neg[ele][A.ele] * A.op;
        ret.ele = c[ele][A.ele];
        return ret;
    }
};
void solve(){
    cin >> n >> x;
    a = RS(str);
    printf("Case #%d: " , ++Case);
    Number pre;
    pre.ONE();
    for (int i = 0 ; i < n ; ++i){
        pre = pre * Number(f(a[i]));
    }
    Number res;res.ONE();
    LL k = x;
    while(k)
    {
        if(k&1) res = res * pre;
        pre = pre * pre, k >>= 1;
    }
    if (res.ele != 0 || res.op != -1){
        puts("NO");
        return;
    }
    L = "";
    if (x > 20) x = 20;
    DO(x) L += a;
    int left = -1 , right = -1;
    res.ONE();
    for (int i = 0 ; i < L.length() ; ++i){
        res = res * Number(f(L[i]));
        if (res.ele == 1 && res.op == 1){
            left = i;
            break;
        }
    }
    res.ONE();
    for (int i = L.length() - 1 ; i >= 0 ; --i){
        res = Number(f(L[i])) * res;
        if (res.ele == 3 && res.op == 1){
            right = i;
            break;
        }
    }
//    cerr << left << ' ' << right << endl;
    puts((left != -1 && right != -1 && left < right) ? "YES" : "NO");
}

Problem D. Ominous Omino

从来没有枚举对过。所以从一开始就没打算去枚举。。

一看,<=20,打表啊!公司机器跑的飞快!

我一看到题,看到这个图


就知道X>=7肯定无解啊,然后就sb地忘了写了23333.

首先是如何枚举Domino块呢,我们想如果按照X = 1 , 2 , 3 。。。 的顺序枚举的话,那么我们只用在 X -> X + 1 的时候枚举一块在已有的Domino周围转一圈,然后去重即可。(我是按照Left-Top的地方戳齐)

然后就是非常暴力地模拟。。找到每一块,然后枚举放在哪个地方,然后剩下的搜。。

怎么搜呢,可以直接再枚举一遍所有的块所有可以放的位置,然后就是一个Dancing Links X Method里面的精确覆盖问题(数据范围那么小是吧。。。)

搜到X = 6 , R = 4 , C = 18 的时候TMD搜不出来了!!于是发现如果 R * C % X == 0 并且 r <= R , c <= C 的 X , r , c 答案是 GABRIEL 的话,那么 R , C 肯定也是。。方法是——


按照这种放法肯定能放下的吧2333

const int maxM = 25 * 25, maxN = 760 * 6 * 6 + 5;
const int max_size = maxN * maxM;
const int inf = 0x3f3f3f3f;
int L[max_size], R[max_size], U[max_size], D[max_size], CH[max_size], RH[max_size];
int S[maxM], O[maxM];
int head, size;
int node(int up, int down, int left, int right) {
    U[size] = up, D[size] = down;
    L[size] = left, R[size] = right;
    D[up] = U[down] = R[left] = L[right] = size;
    return size++;
}
bool mat[maxN][maxM];
void init(int N, int M) {
    size = 0;
    head = node(0, 0, 0, 0);
    for (int j = 1; j <= M; ++j) {
        CH[j] = node(size, size, L[head], head), S[j] = 0;
    }
    for (int i = 1; i <= N; ++i) {
        int row = -1, k;
        for (int j = 1; j <= M; ++j) {
            if (!mat[i][j]) continue;
            if (row == -1) {
                row = node(U[CH[j]], CH[j], size, size);
                RH[row] = i, CH[row] = CH[j], ++S[j];
            } else {
                k = node(U[CH[j]], CH[j], L[row], row);
                RH[k] = i, CH[k] = CH[j], ++S[j];
            }
        }
    }
}
void remove(const int &c) {
    L[R[c]] = L[c], R[L[c]] = R[c];
    for (int i = D[c]; i != c; i = D[i]) {
        for (int j = R[i]; j != i; j = R[j]) {
            U[D[j]] = U[j], D[U[j]] = D[j];
            --S[CH[j]];
        }
    }
}
void resume(const int &c) {
    for (int i = U[c]; i != c; i = U[i]) {
        for (int j = L[i]; j != i; j = L[j]) {
            ++S[CH[j]];
            U[D[j]] = D[U[j]] = j;
        }
    }
    L[R[c]] = R[L[c]] = c;
}
int len;
bool DLX(const int &k) {
    if (R[head] == head) {
        len = k - 1;
        return true;
    }
    int s = inf, c;
    for (int t = R[head]; t != head; t = R[t]) {
        if (S[t] < s) s = S[t], c = t;
    }
    remove(c);
    for (int i = D[c]; i != c; i = D[i]) {
        O[k] = RH[i];
        for (int j = R[i]; j != i; j = R[j]) {
            remove(CH[j]);
        }
        if (DLX(k + 1)) {
            return true;
        }
        for (int j = L[i]; j != i; j = L[j]) {
            resume(CH[j]);
        }
    }
    resume(c);
    return false;
}
int X , RR , CC;
const int DN = 7;
typedef set<PII> :: iterator DITER;
struct Domino{
    set<PII> a;
    bool operator < (const Domino & A) const{
        for(set<PII> :: iterator ia = a.begin() , ib = A.a.begin() ; ia != a.end() && ib != A.a.end() ; ++ia , ++ib){
            if ((*ia) > (*ib)) return false;
            if ((*ia) < (*ib)) return true;
        }
        return false;
    }
    void output(){
        for ( DITER i = a.begin() ; i != a.end() ; ++i)
            cerr << '(' << i -> fi << ',' << i -> se << ')' << ',';
        cerr << endl;
    }
    Domino rot(){
        Domino ret;
        ret.a.clear();
        PII lt = MP(10 , 10);
        for(DITER i = a.begin() ; i != a.end() ; ++i){
            checkMin(lt.fi , -i -> se);
            checkMin(lt.se , i -> fi);
        }
        for(DITER i = a.begin() ; i != a.end() ; ++i){
            ret.a.insert(MP(- i->se - lt.fi , i->fi - lt.se));
        }
        return ret;
    }
}now;
set<Domino> PSet , DSet , checkList;

void Insert(Domino cur){
    PII lt = MP(10 , 10) , nt;
    for (DITER iter = cur.a.begin() ; iter != cur.a.end() ; ++iter){
        checkMin(lt.fi , iter -> fi);
        checkMin(lt.se , iter -> se);
    }
    for (DITER i = cur.a.begin() ; i != cur.a.end() ; ++i){
        for (int d = 0 ; d < 4 ; ++d){
            PII g = MP(i -> fi + dx4[d] , i -> se + dy4[d]);
            if (cur.a.find(g) != cur.a.end()) continue;
            nt = MP(min(lt.fi , g.fi) , min(lt.se , g.se));
            Domino add;
            add.a.clear();
            for ( DITER j = cur.a.begin() ; j != cur.a.end() ; ++j){
                add.a.insert(MP(j -> fi - nt.fi , j -> se - nt.se));
            }
            add.a.insert(MP(g.fi - nt.fi , g.se - nt.se));
            DSet.insert(add);
        }
    }
}
void init(){
    if (X == 1){
        now.a.clear();
        now.a.insert(MP(0 , 0));
        DSet.insert(now);
    }
    else{
        PSet = DSet;
        DSet.clear();
        for (set<Domino> :: iterator iter = PSet.begin() ; iter != PSet.end() ; ++iter)
            Insert(*iter);
    }
    int Count = 0;
    for (set<Domino> :: iterator iter = DSet.begin() ; iter != DSet.end() ; ++iter){
        Domino e = *iter;
        cerr << (++Count) << ":\t";
        e.output();
    }
}
int A[25][25] , num[25][25];
int line;
bool inmap(int x , int y){
    return 0 <= x && x < RR && 0 <= y && y < CC;
}
bool putin(Domino d , int x , int y){
    ++Case;
    for(DITER i = d.a.begin() ; i != d.a.end() ; ++i){
        int gx = x + i -> fi , gy = y + i -> se;
        if (!inmap(gx , gy)) return false;
        A[gx][gy] = Case;
    }
    int c = 0;
    for (int i = 0 ; i < RR ; ++i)
        for (int j = 0 ; j < CC ; ++j)
        if (A[i][j] != Case)
            num[i][j] = ++c;
    if (c == 0) return true;
    line = 1;
    for (int i = 0 ; i < RR ; ++i){
        for (int j = 0 ; j < CC ; ++j){
            for (set<Domino> :: iterator k = DSet.begin() ; k != DSet.end() ; ++k){
                now = *k;
                bool ok = true;
                RST(mat[line]);
                for ( DITER z = now.a.begin() ; ok && z != now.a.end() ; ++z){
                    int gx = i + z -> fi , gy = j + z -> se;
                    if (!inmap(gx , gy) || A[gx][gy] == Case){
                        ok = false;
                        break;
                    }
                    mat[line][num[gx][gy]] = 1;
                    //cerr << line << ' ' << gx << ' ' << gy << ' ' << num[gx][gy] << endl;
                    //getchar();
                }
                if (ok) ++line;
            }
        }
    }
    line--;
    init(line , RR * CC - X);
    if (DLX(0))
        return true;
    return false;
}
bool canput(Domino d){
    if (checkList.find(d) != checkList.end()) return true;
    RST(A);
    Case = 0;
    for (int t = 0 ; t < 4 ; ++t){
        checkList.insert(d);
        d = d.rot();
    }
    for (int t = 0 ; t < 4 ; ++t){
        for (int i = 0 ; i < RR ; ++i)
            for (int j = 0 ; j < CC ; ++j)
                if (putin(d , i , j))
                return true;
        d = d.rot();
    }
    return false;
}
bool check(){
    checkList.clear();
    cerr << "CHECK" << ' ' << X << ' ' << RR << ' ' << CC << endl;
    for (set<Domino> :: iterator iter = DSet.begin() ; iter != DSet.end() ; ++iter){
        if (!canput(*iter)) return true;
    }
    return false;
}
const int MM = 20;
void solve(){
    init();
    vector<PII> okSet ;
    okSet.clear();
    for (RR = 1 ; RR <= MM ; ++RR)
    for (CC = RR ; CC <= MM ; ++CC){
        if (RR * CC % X != 0 || (RR < X && CC < X)){
            cout << "{" << X << ',' << RR << ',' << CC << "},";
            cout << "{" << X << ',' << CC << ',' << RR << "},";
            cerr << "{" << X << ',' << RR << ',' << CC << "}" << endl;
            continue;
        }
        bool pass = false;
        for (int i = 0 ; i < okSet.size() ; ++i)
        if (okSet[i].fi <= RR && okSet[i].se <= CC){
            pass = true;
            continue;
        }
        if (pass) continue;
        if (check()){
            cout << "{" << X << ',' << RR << ',' << CC << "},";
            cout << "{" << X << ',' << CC << ',' << RR << "},";
            cerr << "{" << X << ',' << RR << ',' << CC << "}" << endl;
        }
        else{
            okSet.PB(MP(RR , CC));
        }
    }
}










内容概要:本文介绍了ENVI Deep Learning V1.0的操作教程,重点讲解了如何利用ENVI软件进行深度学习模型的训练与应用,以实现遥感图像中特定目标(如集装箱)的自动提取。教程涵盖了从数据准备、标签图像创建、模型初始化与训练,到执行分类及结果优化的完整流程,并介绍了精度评价与通过ENVI Modeler实现一键化建模的方法。系统基于TensorFlow框架,采用ENVINet5(U-Net变体)架构,支持通过点、线、面ROI或分类图生成标签数据,适用于多/高光谱影像的单一类别特征提取。; 适合人群:具备遥感图像处理基础,熟悉ENVI软件操作,从事地理信息、测绘、环境监测等相关领域的技术人员或研究人员,尤其是希望将深度学习技术应用于遥感目标识别的初学者与实践者。; 使用场景及目标:①在遥感影像中自动识别和提取特定地物目标(如车辆、建筑、道路、集装箱等);②掌握ENVI环境下深度学习模型的训练流程与关键参数设置(如Patch Size、Epochs、Class Weight等);③通过模型调优与结果反馈提升分类精度,实现高效自动化信息提取。; 阅读建议:建议结合实际遥感项目边学边练,重点关注标签数据制作、模型参数配置与结果后处理环节,充分利用ENVI Modeler进行自动化建模与参数优化,同时注意软硬件环境(特别是NVIDIA GPU)的配置要求以保障训练效率。
内容概要:本文系统阐述了企业新闻发稿在生成式引擎优化(GEO)时代下的全渠道策略与效果评估体系,涵盖当前企业传播面临的预算、资源、内容与效果评估四大挑战,并深入分析2025年新闻发稿行业五大趋势,包括AI驱动的智能化转型、精准化传播、首发内容价值提升、内容资产化及数据可视化。文章重点解析央媒、地方官媒、综合门户和自媒体四类媒体资源的特性、传播优势与发稿策略,提出基于内容适配性、时间节奏、话题设计的策略制定方法,并构建涵盖品牌价值、销售转化与GEO优化的多维评估框架。此外,结合“传声港”工具实操指南,提供AI智能投放、效果监测、自媒体管理与舆情应对的全流程解决方案,并针对科技、消费、B2B、区域品牌四大行业推出定制化发稿方案。; 适合人群:企业市场/公关负责人、品牌传播管理者、数字营销从业者及中小企业决策者,具备一定媒体传播经验并希望提升发稿效率与ROI的专业人士。; 使用场景及目标:①制定科学的新闻发稿策略,实现从“流量思维”向“价值思维”转型;②构建央媒定调、门户扩散、自媒体互动的立体化传播矩阵;③利用AI工具实现精准投放与GEO优化,提升品牌在AI搜索中的权威性与可见性;④通过数据驱动评估体系量化品牌影响力与销售转化效果。; 阅读建议:建议结合文中提供的实操清单、案例分析与工具指南进行系统学习,重点关注媒体适配性策略与GEO评估指标,在实际发稿中分阶段试点“AI+全渠道”组合策略,并定期复盘优化,以实现品牌传播的长期复利效应。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值