2020编码大赛(5)半决赛

2020编码大赛题目  2020编码大赛(1)题目_编码赛题-CSDN博客

半决赛,是32个队伍选出8个队伍。

一,需求变更

  • 每个资源区内有多个资源,每个虚拟资源大小不固定,以实际情况为准, 以1024KB为单位大小,如果文件大小为2048KB,则代表两个单位资源,可以兑换两倍的积分与金币。
  • 每个回合每个资源机器人只能进行一次路径调度,可以对该路径上的虚拟资源进行装载,能装载不同类型资源。
  • 资源唯一索引,同时也为该资源位于文件系统的绝对路径。

我的解读:

1,文件大小是1024的倍数
2,可以混合装载
3,调度阶段可以访问文件

二,压缩算法

在写了一个很简单的LZW算法之后,经过多日的攻坚,终于把PPMD写出来了。

 原理:

利用上下文预测,基于比特位去计算,所以涉及大量位运算。

头文件:

#ifndef COMPRESS
#define COMPRESS

#include <string.h>
#include <iostream>
#include <ctime>

typedef unsigned char Byte;
typedef unsigned short UINT16;

#define UPDATE_PROB(prob) ((prob) - (((prob) + 32) >> 7))
#define UPDATE_PROB2(prob) UPDATE_PROB(prob) + 128
#define SYMBOL(s) ((s) >= 64 ? 8 : 0)
#define SYMBOL64(s) SYMBOL((s)->stsym)
#define GETONESTATE(p) ((State *)&(p)->sumfq)
#define CHARMASK(sym) ((char *)charMask)[sym]
#define OFFSET(p, offs) ((offs) + (p)->base)
#define OFFSET2(offs) (unsigned((Byte *)(offs) - (p)->base))
#define GetContext(p, offs) ((Context *)OFFSET((p), (offs)))
#define GetStats(p, ctx) ((State *)OFFSET((p), ((ctx)->ctxStats)))
#define GetStats2(x) GetStats(p, (x))
#define GETNODE(offs) ((Node *)OFFSET((p), (offs)))
#define U2B(x) ((unsigned)(x)*12)
#define U2I(x) (p->unt2id[(size_t)(x)-1])
#define I2U(id) (p->id2unit[id])
#define CTX(offs) GetContext(p, (offs))
#define CTXSUFFIX(x) CTX((x)->ctxSufx)
#define THENEXT(p) ((unsigned)((p)->stnxtlow | ((unsigned)(p)->stnxtHigh << 16)))
#define GET_BIN_SUMM(p)                                                                                                \
    &p->binsum[p->ns2id[(size_t)GETONESTATE(p->minctx)->stfrep - 1]]                                                   \
    [p->ns2bs[GetContext(p, p->minctx->ctxSufx)->ctxNmSats] + p->prev + p->minctx->ctxFlags + ((p->runLen >> 26) & 32)]
    
#define CON1 (p->low ^ (p->low + p->range)) < (1 << 24) || \
        (p->range < (1 << 15) && ((p->range = (0 - p->low) & ((1 << 15) - 1)), 1))
#define MEMCPY(dest, src, num) {                                   \
        unsigned *d = (unsigned *)dest;                            \
        const unsigned *z = (const unsigned *)src;                 \
        unsigned n = num;                                          \
        while (n--) {                                              \
            d[0] = z[0], d[1] = z[1], d[2] = z[2], z += 3, d += 3; \
        }                                                          \
    }

typedef struct  {
    unsigned index, nxn, nnu;
} Node;

typedef struct {
    UINT16 seesum;
    Byte seechg, seecnt;
} See;

typedef struct {
    Byte stsym, stfrep;
    UINT16 stnxtlow, stnxtHigh;
} State;

typedef struct {
    Byte ctxNmSats, ctxFlags;
    UINT16 sumfq;
    unsigned ctxStats, ctxSufx;
} Context;

typedef struct {
    Context *minctx, *maxctx;
    State *st;
    unsigned ordFall, esc, prev, maxord, size, gluecnt, algOff, rstoMth, range, cod, low, frelst[38], idxs[38];
    int runLen, rl, eof;
    Byte *base, *lowUn, *highUn, *tx, *unsat, id2unit[38], unt2id[128], ns2bs[256], ns2id[260];
    See dummy, see[24][32];
    UINT16 binsum[25][64];
} Cpd;

extern clock_t g_start;

void compress();
void decompress();
int compress(std::string s);

#endif

cpp文件:

#include <algorithm>
#include "compress.h"
#include "data.h"
using namespace std;

static const Byte g_kexpEsp[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
static const UINT16 g_kbinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
static int g_mem, g_order, g_com = 0;
static bool g_flag = false;
struct header {
    unsigned magic, attr;
    unsigned short info, fnlen, date, time;
} g_hdr;


static void normalize(Cpd *p)
{
    while (CON1) {
        cout << (Byte)(p->low >> 24);
        p->range <<= 8, p->low <<= 8;
    }
}

static void build(Cpd *p)
{
    int i, k, m;
    p->base = 0;
    for (i = 0, k = 0; i < 38; i++) {
        int step = min(4, i / 4 + 1);
        while (step--) {
            p->unt2id[k++] = (Byte)i;
        }
        p->id2unit[i] = (Byte)k;
    }
    p->ns2bs[0] = 0, p->ns2bs[1] = 2;
    memset(p->ns2bs + 2, 4, 9);
    memset(p->ns2bs + 11, 6, 245);
    for (i = 0; i < 5; i++) {
        p->ns2id[i] = (Byte)i;
    }
    for (m = i, k = 1; i < 260; i++) {
        p->ns2id[i] = (Byte)m;
        if (--k == 0) {
            k = (++m) - 4;
        }
    }
}

static void falloc(Cpd *p, unsigned size)
{
    if (p->base && p->size == size) {
        return;
    }
    free(p->base);
    p->size = 0, p->base = 0, p->algOff = 4 - size % 4, p->base = (Byte *)malloc(p->algOff + size);
    if (!p->base) {
        return;
    }
    p->size = size;
}

static void insertAnode(Cpd *p, void *vp, unsigned indx)
{
    Node *cnode = (Node *)vp;
    cnode->index = 0xFFFFFFFF, cnode->nxn = p->frelst[indx], cnode->nnu = I2U(indx);
    p->frelst[indx] = OFFSET2(cnode), p->idxs[indx]++;
}

static void insertAnode2(Cpd *p, void *ptr, unsigned nu)
{
    unsigned i = U2I(nu);
    if (I2U(i) != nu) {
        unsigned k = I2U(--i);
        insertAnode(p, (Byte *)ptr + U2B(k), nu - k - 1);
    }
    insertAnode(p, ptr, i);
}

static void *removeAnode(Cpd *p, unsigned indx)
{
    Node *node = GETNODE(p->frelst[indx]);
    p->frelst[indx] = node->nxn, p->idxs[indx]--;
    return node;
}

static void split(Cpd *p, void *ptr, unsigned oldIndx, unsigned newIndx)
{
    unsigned nu = I2U(oldIndx) - I2U(newIndx);
    ptr = (Byte *)ptr + U2B(I2U(newIndx));
    insertAnode2(p, ptr, nu);
}

static void bondBlocks(Cpd *p)
{
    unsigned head = 0, *prev = &head, i;
    p->gluecnt = 8192;
    memset(p->idxs, 0, sizeof(p->idxs));
    if (p->lowUn != p->highUn) {
        ((Node *)p->lowUn)->index = 0;
    }
    for (i = 0; i < 38; i++) {
        unsigned next = p->frelst[i];
        p->frelst[i] = 0;
        while (next) {
            Node *node = GETNODE(next);
            if (node->nnu != 0) {
                Node *node2;
                *prev = next, prev = &(node->nxn);
                while (true) {
                    node2 = node + node->nnu;
                    if (node2->index != 0xFFFFFFFF) {
                        break;
                    }
                    node->nnu += node2->nnu, node2->nnu = 0;
                }
            }
            next = node->nxn;
        }
    }
    *prev = 0;
    while (head) {
        Node *node = GETNODE(head);
        unsigned nu;
        head = node->nxn, nu = node->nnu;
        if (!nu) {
            continue;
        }
        while (nu > 128) {
            insertAnode(p, node, 37);
            node += 128;
        }
        insertAnode2(p, node, nu);
    }
}

static void *allocUnits(Cpd *p, unsigned indx)
{
    if (p->gluecnt == 0) {
        bondBlocks(p);
        if (p->frelst[indx]) {
            return removeAnode(p, indx);
        }
    }
    unsigned i = indx, numBytes;
    while (true) {
        if (++i == 38) {
            numBytes = U2B(I2U(indx)), p->gluecnt--;
            return ((unsigned)(p->unsat - p->tx) > numBytes) ? (p->unsat -= numBytes) : (NULL);
        }
        if (p->frelst[i]) {
            break;
        }
    }
    void *retVal = removeAnode(p, i);
    split(p, retVal, i, indx);
    return retVal;
}

static void *allocUnits2(Cpd *p, unsigned indx)
{
    unsigned numBytes;
    if (p->frelst[indx]) {
        return removeAnode(p, indx);
    }
    numBytes = U2B(I2U(indx));
    if (numBytes <= (unsigned)(p->highUn - p->lowUn)) {
        void *retVal = p->lowUn;
        p->lowUn += numBytes;
        return retVal;
    }
    return allocUnits(p, indx);
}

static void *shrink(Cpd *p, void *oldPtr, unsigned oldnnu, unsigned newnnu)
{
    unsigned i = U2I(oldnnu), j = U2I(newnnu);
    if (i == j) {
        return oldPtr;
    }
    if (p->frelst[j]) {
        void *ptr = removeAnode(p, j);
        MEMCPY(ptr, oldPtr, newnnu);
        insertAnode(p, oldPtr, i);
        return ptr;
    }
    split(p, oldPtr, i, j);
    return oldPtr;
}

static void freeUnit(Cpd *p, void *ptr)
{
    if ((Byte *)ptr != p->unsat) {
        insertAnode(p, ptr, 0);
    } else {
        p->unsat += 12;
    }
}

static void *moveUp(Cpd *p, void *oldPtr, unsigned nu)
{
    unsigned indx = U2I(nu);
    if ((Byte *)oldPtr > p->unsat + 16 * 1024 || OFFSET2(oldPtr) > p->frelst[indx]) {
        return oldPtr;
    }
    void *ptr = removeAnode(p, indx);
    MEMCPY(ptr, oldPtr, nu);
    if ((Byte *)oldPtr != p->unsat) {
        insertAnode(p, oldPtr, indx);
    } else {
        p->unsat += U2B(I2U(indx));
    }
    return ptr;
}

static void fnextnode(Cpd *p, unsigned count[])
{
    for (unsigned i = 0; i < 38; i++) {
        unsigned *next = &p->frelst[i];
        while (count[i]) {
            Node *node = GETNODE(*next);
            while (true) {
                if (node->index) {
                    break;
                }
                *next = node->nxn, node = GETNODE(*next), p->idxs[i]--;
                if (--count[i] == 0) {
                    break;
                }
            }
            next = &node->nxn;
        }
    }
}

static void expand(Cpd *p)
{
    unsigned count[38];
    memset(count, 0, sizeof(count));
    if (p->lowUn != p->highUn) {
        ((Node *)p->lowUn)->index = 0;
    }
    Node *node = (Node *)p->unsat;
    while (true) {
        if (node->index != 0xFFFFFFFF) {
            break;
        }
        node->index = 0, count[U2I(node->nnu)]++, node += node->nnu;
    }
    p->unsat = (Byte *)node;
    fnextnode(p, count);
}

static void nextNode(State *p, unsigned v)
{
    p->stnxtlow = (UINT16)(v & 0xFFFF), p->stnxtHigh = (UINT16)((v >> 16) & 0xFFFF);
}

static void rebuild(Cpd *p)
{
    unsigned i, k, m, r;
    memset(p->frelst, 0, sizeof(p->frelst));
    memset(p->idxs, 0, sizeof(p->idxs));
    p->tx = p->base + p->algOff, p->highUn = p->tx + p->size, p->lowUn = p->unsat = p->highUn - p->size / 96 * 84;
    p->gluecnt = 0, p->ordFall = p->maxord, p->prev = 0, p->runLen = p->rl = -min(int(p->maxord), 12) - 1;
    p->minctx = p->maxctx = (Context *)(p->highUn -= 12), p->minctx->ctxSufx = 0, p->minctx->ctxNmSats = 255;
    p->minctx->ctxFlags = 0, p->minctx->sumfq = 256 + 1, p->st = (State *)p->lowUn, p->lowUn += U2B(256 / 2);
    p->minctx->ctxStats = OFFSET2(p->st);
    for (i = 0; i < 256; i++) {
        State *s = &p->st[i];
        s->stsym = (Byte)i, s->stfrep = 1, s->stnxtlow = s->stnxtHigh = 0;
    }
    i = 0;
    for (m = 0; m < 25; m++) {
        while (p->ns2id[i] == m) {
            i++;
        }
        for (k = 0; k < 8; k++) {
            UINT16 val = (UINT16)((1 << 14) - g_kbinEsc[k] / (i + 1)), *dest = p->binsum[m] + k;
            for (r = 0; r < 64; r += 8) {
                dest[r] = val;
            }
        }
    }
    i = 0;
    for (m = 0; m < 24; m++) {
        while (p->ns2id[(size_t)i + 3] == m + 3) {
            i++;
        }
        for (k = 0; k < 32; k++) {
            See *s = &p->see[m][k];
            s->seesum = (UINT16)((2 * i + 5) << (s->seechg = 3)), s->seecnt = 7;
        }
    }
}

static void refresh(Cpd *p, Context *ctx, unsigned oldnnu, unsigned scale)
{
    unsigned i = ctx->ctxNmSats, frp, smfrq, flags;
    State *s = (State *)shrink(p, GetStats2(ctx), oldnnu, (i + 2) >> 1);
    ctx->ctxStats = OFFSET2(s);
    flags = (ctx->ctxFlags & (16 + 4 * scale)) + SYMBOL64(s), frp = ctx->sumfq - s->stfrep;
    smfrq = (s->stfrep = (Byte)((s->stfrep + scale) >> scale));
    while (i--) {
        frp -= (++s)->stfrep, s->stfrep = (Byte)((s->stfrep + scale) >> scale);
        smfrq += s->stfrep, flags |= SYMBOL64(s);
    }
    ctx->sumfq = (UINT16)(smfrq + ((frp + scale) >> scale)), ctx->ctxFlags = (Byte)flags;
}

static void exchange(State *t1, State *t2)
{
    State tmp = *t1;
    *t1 = *t2, *t2 = tmp;
}

static unsigned cutoff(Cpd *p, Context *ctx, unsigned order)
{
    int i;
    unsigned tmp;
    State *s;
    if (!ctx->ctxNmSats) {
        s = GETONESTATE(ctx);
        if ((Byte *)OFFSET(p, THENEXT(s)) >= p->unsat) {
            tmp = (order < p->maxord) ? cutoff(p, CTX(THENEXT(s)), order + 1) : 0;
            nextNode(s, tmp);
            if (THENEXT(s) || order <= 9) {
                return OFFSET2(ctx);
            }
        }
        freeUnit(p, ctx);
        return 0;
    }
    ctx->ctxStats = OFFSET2(moveUp(p, GetStats2(ctx), tmp = ((unsigned)ctx->ctxNmSats + 2) >> 1));
    for (s = GetStats2(ctx) + (i = ctx->ctxNmSats); s >= GetStats2(ctx); s--) {
        if ((Byte *)OFFSET(p, THENEXT(s)) < p->unsat) {
            State *s2 = GetStats2(ctx) + (i--);
            s->stnxtlow = s->stnxtHigh = 0;
            exchange(s, s2);
        } else {
            tmp = (order < p->maxord) ? cutoff(p, CTX(THENEXT(s)), order + 1) : 0;
            nextNode(s, tmp);
        }
    }
    if (i != ctx->ctxNmSats && order) {
        ctx->ctxNmSats = (Byte)i;
        s = GetStats2(ctx);
        if (i < 0) {
            insertAnode(p, s, U2I(tmp));
            freeUnit(p, ctx);
            return 0;
        }
        if (i == 0) {
            ctx->ctxFlags = (Byte)((ctx->ctxFlags & 16) + SYMBOL64(s));
            *GETONESTATE(ctx) = *s;
            insertAnode(p, s, U2I(tmp));
            GETONESTATE(ctx)->stfrep = (Byte)(((unsigned)GETONESTATE(ctx)->stfrep + 11) >> 3);
        } else {
            refresh(p, ctx, tmp, ctx->sumfq > 16 * i);
        }
    }
    return OFFSET2(ctx);
}

static unsigned getUsedNode(const Cpd *p)
{
    unsigned v = 0;
    for (unsigned i = 0; i < 38; i++) {
        v += p->idxs[i] * I2U(i);
    }
    return p->size - (unsigned)(p->highUn - p->lowUn) - (unsigned)(p->unsat - p->tx) - U2B(v);
}

static void restore(Cpd *p, Context *c1)
{
    Context *c;
    State *s;
    p->tx = p->base + p->algOff;
    for (c = p->maxctx; c != c1; c = CTXSUFFIX(c)) {
        if (--(c->ctxNmSats) == 0) {
            s = GetStats2(c), c->ctxFlags = (Byte)((c->ctxFlags & 16) + SYMBOL64(s)), *GETONESTATE(c) = *s;
            freeUnit(p, s);
            GETONESTATE(c)->stfrep = (Byte)(((unsigned)GETONESTATE(c)->stfrep + 11) >> 3);
        } else {
            refresh(p, c, (c->ctxNmSats + 3) >> 1, 0);
        }
    }
    while (true) {
        if (c == p->minctx) {
            break;
        }
        if (!c->ctxNmSats) {
            GETONESTATE(c)->stfrep = (Byte)(GETONESTATE(c)->stfrep - (GETONESTATE(c)->stfrep >> 1));
        } else if ((c->sumfq += 4) > 128 + 4 * c->ctxNmSats) {
            refresh(p, c, (c->ctxNmSats + 2) >> 1, 1);
        }
        c = CTXSUFFIX(c);
    }
    if (p->rstoMth == 0 || getUsedNode(p) < (p->size >> 1)) {
        return rebuild(p);
    }
    while (p->maxctx->ctxSufx) {
        p->maxctx = CTXSUFFIX(p->maxctx);
    }
    while (true) {
        cutoff(p, p->maxctx, 0);
        expand(p);
        if (getUsedNode(p) <= 3 * (p->size >> 2)) {
            break;
        }
    }
    p->gluecnt = 0, p->ordFall = p->maxord;
}

static Context *createnxn(Cpd *p, int skip, State *s1, Context *c)
{
    State upState;
    Byte flags;
    unsigned ubra = THENEXT(p->st), numPs = 0;
    State *ps[17];
    if (!skip) {
        ps[numPs++] = p->st;
    }
    while (c->ctxSufx) {
        unsigned ssor;
        State *s;
        c = CTXSUFFIX(c);
        if (s1) {
            s = s1, s1 = NULL;
        } else if (c->ctxNmSats != 0) {
            s = GetStats2(c);
            while (s->stsym != p->st->stsym) {
                s++;
            }
            if (s->stfrep < 115) {
                s->stfrep++, c->sumfq++;
            }
        } else {
            s = GETONESTATE(c), s->stfrep = (Byte)(s->stfrep + (!CTXSUFFIX(c)->ctxNmSats & (s->stfrep < 24)));
        }
        ssor = THENEXT(s);
        if (ssor != ubra) {
            c = CTX(ssor);
            if (numPs == 0) {
                return c;
            }
            break;
        }
        ps[numPs++] = s;
    }
    upState.stsym = *(Byte *)OFFSET(p, ubra);
    nextNode(&upState, ubra + 1);
    flags = SYMBOL64(p->st) * 2 + SYMBOL64(&upState);
    if (c->ctxNmSats == 0) {
        upState.stfrep = GETONESTATE(c)->stfrep;
    } else {
        unsigned cf, s0;
        State *s = GetStats2(c);
        while (s->stsym != upState.stsym) {
            s++;
        }
        cf = s->stfrep - 1, s0 = c->sumfq - c->ctxNmSats - cf;
        upState.stfrep = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));
    }
    while (true) {
        Context *c1;
        if (p->highUn != p->lowUn) {
            c1 = (Context *)(p->highUn -= 12);
        } else {
            c1 = (Context *)(p->frelst[0] ? removeAnode(p, 0) : allocUnits(p, 0));
        }
        if (!c1) {
            return NULL;
        }
        c1->ctxNmSats = 0, c1->ctxFlags = flags, *GETONESTATE(c1) = upState, c1->ctxSufx = OFFSET2(c), c = c1;
        nextNode(ps[--numPs], OFFSET2(c1));
        if (numPs == 0) {
            break;
        }
    }
    return c;
}

static Context *reduce(Cpd *p, State *s1, Context *c)
{
    State *s = NULL;
    Context *c1 = c;
    unsigned upBranch = OFFSET2(p->tx);
    nextNode(p->st, upBranch);
    p->ordFall++;
    while (true) {
        if (s1) {
            c = CTXSUFFIX(c), s = s1, s1 = NULL;
        } else {
            if (!c->ctxSufx) {
                return c;
            }
            c = CTXSUFFIX(c);
            if (c->ctxNmSats) {
                s = GetStats2(c);
                if (s->stsym != p->st->stsym) {
                    s++;
                    while (s->stsym != p->st->stsym) {
                        s++;
                    }
                }
                if (s->stfrep < 115) {
                    s->stfrep += 2, c->sumfq += 2;
                }
            } else {
                s = GETONESTATE(c), s->stfrep = (Byte)(s->stfrep + (s->stfrep < 32));
            }
        }
        if (THENEXT(s)) {
            break;
        }
        nextNode(s, upBranch);
        p->ordFall++;
    }
    if (THENEXT(s) <= upBranch) {
        State *s2 = p->st;
        p->st = s;
        Context *ssor = createnxn(p, false, NULL, c);
        if (!ssor) {
            s->stnxtlow = s->stnxtHigh = 0;
        } else {
            nextNode(s, OFFSET2(ssor));
        }
        p->st = s2;
    }
    if (p->ordFall == 1 && c1 == p->maxctx) {
        nextNode(p->st, THENEXT(s));
        p->tx--;
    }
    return THENEXT(s) ? CTX(THENEXT(s)) : NULL;
}

static void update(Cpd *p)
{
    unsigned ssor, fsor = THENEXT(p->st);
    Context *c;
    unsigned s0, ns, fstfrep = p->st->stfrep;
    Byte flag, fstsym = p->st->stsym;
    State *s = NULL;
    if (p->st->stfrep < 31 && p->minctx->ctxSufx != 0) {
        c = CTXSUFFIX(p->minctx);
        if (c->ctxNmSats == 0) {
            s = GETONESTATE(c);
            if (s->stfrep < 32) {
                s->stfrep++;
            }
        } else {
            s = GetStats2(c);
            if (s->stsym != p->st->stsym) {
                s++;
                while (s->stsym != p->st->stsym) {
                    s++;
                }
                if (s[0].stfrep >= s[-1].stfrep) {
                    exchange(&s[0], &s[-1]);
                    s--;
                }
            }
            if (s->stfrep < 115) {
                s->stfrep += 2, c->sumfq += 2;
            }
        }
    }
    c = p->maxctx;
    if (p->ordFall == 0 && fsor) {
        Context *cs = createnxn(p, true, s, p->minctx);
        if (cs == 0) {
            p->st->stnxtlow = p->st->stnxtHigh = 0;
            restore(p, c);
        } else {
            nextNode(p->st, OFFSET2(cs));
            p->maxctx = cs;
        }
        return;
    }
    *p->tx++ = p->st->stsym;
    ssor = OFFSET2(p->tx);
    if (p->tx >= p->unsat) {
        return restore(p, c);
    }
    if (!fsor) {
        Context *cs = reduce(p, s, p->minctx);
        if (!cs) {
            return restore(p, c);
        }
        fsor = OFFSET2(cs);
    } else if ((Byte *)OFFSET(p, fsor) < p->unsat) {
        Context *cs = createnxn(p, false, s, p->minctx);
        if (!cs) {
            return restore(p, c);
        }
        fsor = OFFSET2(cs);
    }
    if (--p->ordFall == 0) {
        ssor = fsor, p->tx -= (p->maxctx != p->minctx);
    }
    s0 = p->minctx->sumfq - (ns = p->minctx->ctxNmSats) - fstfrep, flag = SYMBOL(fstsym);
    while (c != p->minctx) {
        unsigned ns1 = c->ctxNmSats;
        if (ns1 & 1) {
            unsigned oldnnu = (ns1 + 1) >> 1, i = U2I(oldnnu);
            if (i != U2I((size_t)oldnnu + 1)) {
                void *ptr = allocUnits2(p, i + 1), *oldPtr;
                if (!ptr) {
                    return restore(p, c);
                }
                oldPtr = GetStats2(c);
                MEMCPY(ptr, oldPtr, oldnnu);
                insertAnode(p, oldPtr, i);
                c->ctxStats = OFFSET2(ptr);
            }
        }
        if (ns1) {
            c->sumfq = (UINT16)(c->sumfq + (3 * ns1 + 1 < ns));
        } else {
            State *s2 = (State *)allocUnits2(p, 0);
            if (!s2) {
                restore(p, c);
                return;
            }
            *s2 = *GETONESTATE(c), c->ctxStats = OFFSET2(s2), s2->stfrep = (s2->stfrep < 30) ? s2->stfrep * 2 : 120;
            c->sumfq = (UINT16)(s2->stfrep + p->esc + (ns > 2));
        }
        unsigned cf = 2 * fstfrep * (c->sumfq + 6), sf = (unsigned)s0 + c->sumfq;
        if (cf < 6 * sf) {
            cf = 1 + (cf > sf) + (cf >= 4 * sf), c->sumfq += 4;
        } else {
            cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf), c->sumfq = (UINT16)(c->sumfq + cf);
        }
        State *s2 = GetStats2(c) + ns1 + 1;
        nextNode(s2, ssor);
        s2->stsym = fstsym, s2->stfrep = (Byte)cf, c->ctxFlags |= flag, c->ctxNmSats = (Byte)(ns1 + 1);
        c = CTXSUFFIX(c);
    }
    p->maxctx = p->minctx = CTX(fsor);
}

static void rescale(Cpd *p)
{
    unsigned i, adder, sumstfrep, escstfrep;
    State *stats = GetStats2(p->minctx), *s = p->st;
    State tmp = *s;
    while (s != stats) {
        s[0] = s[-1], s--;
    }
    *s = tmp, escstfrep = p->minctx->sumfq - s->stfrep, s->stfrep += 4, adder = (p->ordFall != 0);
    s->stfrep = (Byte)((s->stfrep + adder) / 2), sumstfrep = s->stfrep, i = p->minctx->ctxNmSats;
    do {
        escstfrep -= (++s)->stfrep, s->stfrep = (Byte)((s->stfrep + adder) / 2), sumstfrep += s->stfrep;
        if (s[0].stfrep > s[-1].stfrep) {
            State *s1 = s, tmp = *s1;
            s1[0] = s1[-1];
            while (--s1 != stats && tmp.stfrep > s1[-1].stfrep) {
                s1[0] = s1[-1];
            }
            *s1 = tmp;
        }
    } while (--i);
    if (!s->stfrep) {
        unsigned numctxStats = p->minctx->ctxNmSats;
        i++;
        while (!(--s)->stfrep) {
            i++;
        }
        escstfrep += i;
        p->minctx->ctxNmSats = (Byte)(p->minctx->ctxNmSats - i);
        if (!p->minctx->ctxNmSats) {
            State tmp = *stats;
            tmp.stfrep = (Byte)((2 * tmp.stfrep + escstfrep - 1) / escstfrep);
            tmp.stfrep = min(tmp.stfrep, Byte(41));
            insertAnode(p, stats, U2I((numctxStats + 2) >> 1));
            p->minctx->ctxFlags = (Byte)((p->minctx->ctxFlags & 16) + SYMBOL64(&tmp));
            *(p->st = GETONESTATE(p->minctx)) = tmp;
            return;
        }
        unsigned n0 = numctxStats / 2 + 1, n1 = p->minctx->ctxNmSats / 2 + 1;
        if (n0 != n1) {
            p->minctx->ctxStats = OFFSET2(shrink(p, stats, n0, n1));
        }
        p->minctx->ctxFlags &= -9, s = GetStats2(p->minctx), p->minctx->ctxFlags |= SYMBOL64(s);
        i = p->minctx->ctxNmSats;
        while (i--) {
            p->minctx->ctxFlags |= SYMBOL64(++s);
        }
    }
    p->minctx->sumfq = (UINT16)(++escstfrep / 2 + sumstfrep), p->minctx->ctxFlags |= 4, p->st = GetStats2(p->minctx);
}

See *makestfrep(Cpd *p, unsigned numMasked1, unsigned *escstfrep)
{
    See *see;
    if (p->minctx->ctxNmSats != 255) {
        unsigned r, tmp = (2 * p->minctx->ctxNmSats < CTXSUFFIX(p->minctx)->ctxNmSats + numMasked1) ? 2 : 0;
        see = p->see[p->ns2id[p->minctx->ctxNmSats + 2] - 3] + tmp + p->minctx->ctxFlags;
        see += (p->minctx->sumfq > 11 * (p->minctx->ctxNmSats + 1)) ? 1 : 0;
        r = (see->seesum >> see->seechg), see->seesum = (UINT16)(see->seesum - r), *escstfrep = r + (!r);
    } else {
        see = &p->dummy, *escstfrep = 1;
    }
    return see;
}

static void nextContext(Cpd *p)
{
    Context *c = CTX(THENEXT(p->st));
    if (p->ordFall == 0 && (Byte *)c >= p->unsat) {
        p->minctx = p->maxctx = c;
    } else {
        update(p);
        p->minctx = p->maxctx;
    }
}

void update2(Cpd *p)
{
    State *s = p->st;
    s->stfrep += 4, p->minctx->sumfq += 4;
    if (s[0].stfrep > s[-1].stfrep) {
        exchange(&s[0], &s[-1]);
        p->st = --s;
        if (s->stfrep > 124) {
            rescale(p);
        }
    }
    nextContext(p);
}

void update3(Cpd *p)
{
    p->prev = (2 * p->st->stfrep >= p->minctx->sumfq), p->runLen += p->prev, p->minctx->sumfq += 4;
    if ((p->st->stfrep += 4) > 124) {
        rescale(p);
    }
    nextContext(p);
}

void updateBin(Cpd *p)
{
    p->st->stfrep = p->st->stfrep + (p->st->stfrep < 196), p->prev = 1, p->runLen++;
    nextContext(p);
}

void update4(Cpd *p)
{
    p->minctx->sumfq += 4;
    if ((p->st->stfrep += 4) > 124) {
        rescale(p);
    }
    p->runLen = p->rl;
    update(p);
    p->minctx = p->maxctx;
}

Byte readchar(int &e)
{
    if (e) {
        return 0;
    }
    int c = getc(stdin);
    if (c == EOF) {
        e = 1;
        return 0;
    }
    return c;
}

static void encode(Cpd *p, unsigned start, unsigned size, unsigned total)
{
    p->range /= total, p->low += start * p->range, p->range *= size;
    normalize(p);
}

static int fcontext(Cpd *p, unsigned numMasked)
{
    while (true) {
        p->ordFall++;
        if (!p->minctx->ctxSufx) {
            return 1;
        }
        p->minctx = GetContext(p, p->minctx->ctxSufx);
        if (p->minctx->ctxNmSats != numMasked) {
            break;
        }
    }
    return 0;
}

static int ffreq(Cpd *p, unsigned numMasked, int symbol, size_t charMask[])
{
    unsigned escstfrep;
    See *see = makestfrep(p, numMasked, &escstfrep);
    State *s = GetStats(p, p->minctx);
    unsigned sum = 0, i = p->minctx->ctxNmSats + 1;

    while (i--) {
        int cur = s->stsym;
        if (cur == symbol) {
            unsigned low = sum;
            State *s1 = s;
            i++;
            while (i--) {
                sum += (s->stfrep & (int)(CHARMASK(s->stsym))), s++;
            }
            encode(p, low, s1->stfrep, sum + escstfrep);
            if (see->seechg < 7 && --see->seecnt == 0) {
                see->seesum <<= 1, see->seecnt = (Byte)(3 << see->seechg++);
            }
            p->st = s1;
            update4(p);

            return 1;
        }
        sum += (s->stfrep & (int)(CHARMASK(cur))), CHARMASK(cur) = 0, s++;
    }

    encode(p, sum, escstfrep, sum + escstfrep);
    see->seesum = (UINT16)(see->seesum + sum + escstfrep);
    return 0;
}

static int fstats(Cpd *p, int symbol, size_t charMask[])
{
    State *s = GetStats(p, p->minctx);
    unsigned sum, i;
    if (s->stsym == symbol) {
        encode(p, 0, s->stfrep, p->minctx->sumfq);
        p->st = s;
        update3(p);
        return 1;
    }
    p->prev = 0, sum = s->stfrep, i = p->minctx->ctxNmSats;
    while (i--) {
        if ((++s)->stsym == symbol) {
            encode(p, sum, s->stfrep, p->minctx->sumfq);
            p->st = s;
            update2(p);
            return 1;
        }
        sum += s->stfrep;
    }
    memset(charMask, -1, 256);
    CHARMASK(s->stsym) = 0;
    i = p->minctx->ctxNmSats;
    while (i--) {
        CHARMASK((--s)->stsym) = 0;
    }
    encode(p, sum, p->minctx->sumfq - sum, p->minctx->sumfq);
    return 0;
}

static int fstats2(Cpd *p, int symbol, size_t charMask[])
{
    UINT16 *prob = GET_BIN_SUMM(p);
    State *s = GETONESTATE(p->minctx);
    if (s->stsym == symbol) {
        p->range >>= 14, p->range *= *prob;
        normalize(p);
        *prob = (UINT16)UPDATE_PROB2(*prob), p->st = s;
        updateBin(p);
        return 1;
    } else {
        p->range >>= 14, p->low += *prob * p->range, p->range *= ((1 << 14) - *prob);
        normalize(p);
        *prob = (UINT16)UPDATE_PROB(*prob), p->esc = g_kexpEsp[*prob >> 10];
        memset(charMask, -1, 256);
        CHARMASK(s->stsym) = 0, p->prev = 0;
    }
    return 0;
}

void encodestsym(Cpd *p, int symbol)
{
    size_t charMask[256 / sizeof(size_t)];
    if (p->minctx->ctxNmSats) {
        if (fstats(p, symbol, charMask)) {
            return;
        }
    } else {
        if (fstats2(p, symbol, charMask)) {
            return;
        }
    }
    while (true) {
        unsigned numMasked = p->minctx->ctxNmSats;
        if (fcontext(p, numMasked)) {
            return;
        }
        if (ffreq(p, numMasked, symbol, charMask)) {
            return;
        }
    }
}

static void decode(Cpd *p, unsigned start, unsigned size)
{
    start *= p->range, p->low += start, p->cod -= start, p->range *= size;
    while (CON1) {
        p->cod = (p->cod << 8) | readchar(p->eof), p->range <<= 8, p->low <<= 8;
    }
}

static int fstats3(Cpd *p, size_t charMask[])
{
    State *s = GetStats(p, p->minctx);
    unsigned count = p->cod / (p->range /= p->minctx->sumfq), hiCnt = s->stfrep;
    if (count < hiCnt) {
        decode(p, 0, s->stfrep);
        p->st = s;
        Byte ret = s->stsym;
        update3(p);
        return ret;
    }
    p->prev = 0;
    unsigned i = p->minctx->ctxNmSats;
    while (i--) {
        if ((hiCnt += (++s)->stfrep) > count) {
            decode(p, hiCnt - s->stfrep, s->stfrep);
            p->st = s;
            Byte ret = s->stsym;
            update2(p);
            return ret;
        }
    }
    if (count >= p->minctx->sumfq) {
        return -2;
    }
    decode(p, hiCnt, p->minctx->sumfq - hiCnt);
    memset(charMask, -1, 256);
    CHARMASK(s->stsym) = 0;
    i = p->minctx->ctxNmSats;
    while (i--) {
        CHARMASK((--s)->stsym) = 0;
    }
    return -1;
}

static int fstats4(Cpd *p, size_t charMask[])
{
    UINT16 *prob = GET_BIN_SUMM(p);
    if (((p->cod / (p->range >>= 14)) < *prob)) {
        decode(p, 0, *prob);
        *prob = (UINT16)UPDATE_PROB2(*prob), p->st = GETONESTATE(p->minctx);
        Byte ret = p->st->stsym;
        updateBin(p);
        return ret;
    }
    decode(p, *prob, (1 << 14) - *prob);
    *prob = (UINT16)UPDATE_PROB(*prob);
    p->esc = g_kexpEsp[*prob >> 10];
    memset(charMask, -1, 256);
    CHARMASK(GETONESTATE(p->minctx)->stsym) = 0;
    p->prev = 0;
    return -1;
}

static int ffreq2(Cpd *p, size_t charMask[])
{
    State *ps[256], *s;
    unsigned hiCnt, i, num, numMasked = p->minctx->ctxNmSats, freqSum, count;
    while (true) {
        p->ordFall++;
        if (!p->minctx->ctxSufx) {
            return -1;
        }
        p->minctx = GetContext(p, p->minctx->ctxSufx);
        if (p->minctx->ctxNmSats != numMasked) {
            break;
        }
    }
    hiCnt = 0, s = GetStats(p, p->minctx), i = 0, num = p->minctx->ctxNmSats - numMasked;
    while (true) {
        int k = (int)(CHARMASK(s->stsym));
        hiCnt += (s->stfrep & k), ps[i] = s++, i -= k;
        if (i == num) {
            break;
        }
    }
    See *see;
    see = makestfrep(p, numMasked, &freqSum), freqSum += hiCnt, count = p->cod / (p->range /= freqSum);
    if (count < hiCnt) {
        Byte ret;
        State **pps = ps;
        hiCnt = 0;
        while (true) {
            hiCnt += (*pps)->stfrep;
            if (hiCnt > count) {
                break;
            }
            pps++;
        }
        s = *pps;
        decode(p, hiCnt - s->stfrep, s->stfrep);
        if (see->seechg < 7 && --see->seecnt == 0) {
            see->seesum <<= 1, see->seecnt = (Byte)(3 << see->seechg++);
        }
        p->st = s, ret = s->stsym;
        update4(p);
        return ret;
    }
    if (count >= freqSum) {
        return -2;
    }
    decode(p, hiCnt, freqSum - hiCnt);
    see->seesum = (UINT16)(see->seesum + freqSum);
    while (true) {
        CHARMASK(ps[--i]->stsym) = 0;
        if (!i) {
            break;
        }
    }
    return -3;
}

int decodestsym(Cpd *p)
{
    size_t charMask[256 / sizeof(size_t)];
    int ret;
    if (p->minctx->ctxNmSats != 0) {
        ret = fstats3(p, charMask);
    } else {
        ret = fstats4(p, charMask);
    }
    if (ret != -1) {
        return ret;
    }
    while (true) {
        ret = ffreq2(p, charMask);
        if (ret != -3) {
            return ret;
        }
    }
}

static void init(Cpd &ppmd)
{
    g_mem = 8, g_order = 6, g_hdr = { 0, 0, 32885, 1, 0, 0 };
    build(&ppmd);
    falloc(&ppmd, g_mem << 20);
    ppmd.low = 0, ppmd.range = 0xFFFFFFFF, ppmd.maxord = 6, ppmd.rstoMth = 0, ppmd.dummy.seechg = 7;
    rebuild(&ppmd);
}

void compress()
{
    Cpd ppmd;
    init(ppmd);
    unsigned char buf[BUFSIZ];
    while (true) {
        size_t n = fread(buf, 1, sizeof(buf), stdin);
        if (!n) {
            break;
        }
        for (size_t i = 0; i < n; i++) {
            encodestsym(&ppmd, buf[i]);
        }
    }
    encodestsym(&ppmd, -1);
    for (int i = 0; i < 4; i++, ppmd.low <<= 8) {
        cout << (Byte)(ppmd.low >> 24);
    }
}

void decompress()
{
    Cpd ppmd;
    init(ppmd);
    for (int i = 0; i < 4; i++) {
        ppmd.cod = (ppmd.cod << 8) | readchar(ppmd.eof);
    }
    while (true) {
        int c = decodestsym(&ppmd);
        if (ppmd.eof || c < 0) {
            break;
        }
        cout << (Byte)c;
    }
}

压缩率:

2:7,也就是说一般情况下可以装载7份

这里列出了1M、2M、3M的文件压缩后的大小:

性能:

压缩1M需要0.4秒,压缩7M需要2S

三,变更应对

1,文件大小是1024的倍数

这部分简单,只需要修改计算容量的方式即可

// 矿堆所有矿的大小之和
static int getUnitsSize(vector<ResourceUnit> v)
{
    int ans = 0;
    for (unsigned i = 0; i < v.size(); i++) {
        ans += v[i].sizeOfUnit / 1024;
    }
    return ans;
}
// 矿堆所有矿的大小之和
static int getResourceNum(Pos p)
{
    if (samePos(p, g_posFlag)) {
        return 0;
    }
    return getUnitsSize(g_resourceUnits[p.x][p.y]);
}

2,可以混合装载

可以混合装载的话,就可以衍生出很多策略。

我加入了一个很重要的机制:把选矿和选矿堆2个逻辑进行分离,先选定矿堆,然后把所有矿堆的所有矿放在一起进行挑选

// 这条路径要装载多少M资源是>=col颜色的
static int getPathPower(vector<Pos> p, int col)
{
    int ans = 0;
    for (unsigned int i = 1; i < p.size(); i++) {
        if (avail(p[i], g_mapEntities) && g_mapEntities[p[i].x][p[i].y] >= col) {
            ans += getResourceNum(p[i]);
        }
    }
    if (ans > remainSize()) {
        return remainSize();
    }
    return ans;
}

// 第一次调用,path是worker到基地这2个点
static bool getTarget(vector<Pos> &path, int col)
{
    map<pair<int, int>, int> m;
    Pos tmp;
    for (int i = 1; i <= g_height; i++) {
        for (int j = 1; j <= g_width; j++) {
            tmp.x = i, tmp.y = j;
            if (g_mapEntities[i][j] == col) {
                int num = 0;
                m[make_pair(i, j)] = targetAvail(*(path.end() - 2), tmp, *(path.end() - 1), num) * 8;
                m[make_pair(i, j)] += num;
            }
        }
    }
    tmp = getMinPos(m);
    vector<Pos> temp;
    if (!samePos(tmp, Pos { 0, 0 })) {
        getPath(*(path.end() - 2), tmp, g_mapEntities, temp);
        killMap(temp, g_mapEntities);
        g_myTeam.worker.power -= temp.size() + getPathPower(temp, col);
        path.insert(path.end() - 1, tmp);
        return true;
    }
    return false;
}

static void play(Pos start, Pos end, vector<Pos> &path)
{
    vector<Pos> tar(2);
    tar[0] = start;
    tar[1] = end;
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            g_mapEntities2[i][j] = g_mapEntities[i][j];
        }
    }
    g_power2 = g_myTeam.worker.power;
    while (getPathSize(tar) < remainSize() && g_myTeam.worker.power > 0) {
        if (!getTarget(tar, RED)) {
            break;
        }
    }
    while (getPathSize(tar) < remainSize() && g_myTeam.worker.power > 0) {
        if (!getTarget(tar, GREEN)) {
            break;
        }
    }
    while (getPathSize(tar) < remainSize() && g_myTeam.worker.power > 0) {
        if (!getTarget(tar, BLUE)) {
            break;
        }
    }
    g_myTeam.worker.power = g_power2;
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            g_mapEntities[i][j] = g_mapEntities2[i][j];
        }
    }
    if (samePos(*(tar.end() - 1), g_posFlag)) {
        tar.erase(tar.end() - 1);
    }
    int ret = getPath(tar, path);
    if (ret == -1) {
        cout << endl << "play1()    ret = -1" << endl;
        return;
    }
}

从矿堆的所有矿中,挑选矿的方法就是,先排序,再按顺序装载

static bool cmp(ResourceUnit a, ResourceUnit b)
{
    if (a.gemType != b.gemType) {
        return a.gemType > b.gemType;
    }
    return a.sizeOfUnit > b.sizeOfUnit;
}
// 从矿堆里面选矿
static vector<ResourceUnit> take(vector<Pos> p, int num, int &power)
{
    vector<ResourceUnit> ans, tmp;
    for (unsigned i = 0; i < p.size(); i++) {
        Pos po = p[i];
        for (unsigned i = 0; i < g_resourceUnits[po.x][po.y].size(); i++) {
            tmp.push_back(g_resourceUnits[po.x][po.y][i]);
        }
    }
    sort(tmp.begin(), tmp.end(), cmp);
    int rm = g_myTeam.worker.maxLoad - g_myTeam.worker.load, s = 0;
    num = power = 0;
    for (unsigned i = 0; i < tmp.size(); i++) {
        cout << endl << "begin " << tmp[i].sizeOfUnit << " " << clock() << " ";
        int ret = compress(tmp[i].index);
        cout << " end " << clock() << endl;
        if (ret + s > rm) {
            continue;
        }
        ans.push_back(tmp[i]);
        s += ret, num++, power += tmp[i].sizeOfUnit / 1024 * tmp[i].gemType;
    }
    return ans;
}
static vector<ResourceUnit> take(vector<Pos> p)
{
    int num, power;
    return take(p, num, power);
}

static void play()
{
    Pos workerPos = g_myTeam.worker.pos;
    if (!startAtCamp() && canGotoCamp()) {
        play(workerPos, g_myTeam.campPos, g_path);
        int num, pow;
        vector<ResourceUnit> vans = take(g_path, num, pow);
        setCollectCommands(vans);
        g_myTeam.worker.power -= g_path.size() - 1 + vans.size() - pow;
        killMap(g_path, g_mapEntities);
        workerPos = *(g_path.end() - 1), g_myTeam.worker.load = 0;
        g_myTeam.worker.loadInfo.clear();
        vector<Pos> path;
        play(workerPos, g_posFlag, path);
        setCollectCommands(take(path));
        if (path.size()) {
            path.erase(path.begin());
        }
        g_path = join(g_path, path);
        return;
    }
    play(workerPos, g_posFlag, g_path);
    setCollectCommands(take(g_path));
}

cmp函数里面蕴含了一个策略:先装大的再装小的,因为我的压缩算法压缩大文件压缩率更高

PS:我没有仔细研究这一点,或许是和待压缩文件有关,和算法无关。真相不重要,结果都一样。

3,调度阶段可以访问文件

我的压缩算法没有别人的压缩率高,但是压缩很快,所以这个优势要利用起来。

经过简单的计算,发现10秒完全可以胜任16M的压缩任务,所以这里有个重要的策略:

在选出矿堆并把所有矿排序之后,按顺序一边装载一边调用压缩接口,实时计算剩余空间,这样才能尽量装满。

为了加速,我加了标记,在调度的时候调用压缩接口的话,就不需要输出,从而加速程序运行。

static void normalize(Cpd *p)
{
    if (g_flag) {
        while (CON1) {
            p->range <<= 8, p->low <<= 8, g_com++;
        }
    }
    while (CON1) {
        cout << (Byte)(p->low >> 24);
        p->range <<= 8, p->low <<= 8;
    }
}

int compress(string s)
{
    freopen(s.c_str(), "r", stdin);
    g_com = 0, g_flag = true;
    if (clock() - g_start > 6 * CLOCKS_PER_SEC) { // 这个分支应该走不到
        return COMSIZE;
    }
    compress();
    return g_com / 1024 + 1;
}

上面的take函数里面调用了这个compress重载函数。

为了保证不超时,我还加入了定时机制,只在压缩入口处加了定时。

在最后的决赛中,我发现这里写的有个问题,当时间超过阈值时,也不应该直接返回常数COMSIZE,而应该根据历史压缩记录去评估。(这个函数本来就已经有了)

四,未上线策略

有个策略我想到了,而且写的差不多了,但最终还是没上线,主要是来不及调试。

在选矿堆的时候,我是先选红矿,再选绿矿,再选蓝矿,矿堆被选取的顺序和被走到的顺序是一样的,即走过的路径肯定是红红红绿绿蓝蓝蓝这种的。

然而实际上,如果在从一个红矿走到另外一个红矿的过程中经过了绿矿,当我决定开始选绿矿的时候,应该先把这些经过的绿矿加入到待选列表中

// 添加经过的矿堆
static vector<Pos> extend(vector<Pos> v, int col)
{
    if (v.size() < 2) {
        return v;
    }
    Pos tmp = *(v.end() - 1);
    v.erase(v.end() - 1);
    vector<Pos> ans, path;
    getPath(v, path);
    ans.push_back(path[0]);
    for (int i = 0; i < path.size() - 1; i++) {
        if (g_mapEntities[path[i].x][path[i].y] >= col) {
            ans.push_back(path[i]);
        }
    }
    if (path.size() - 1 > 0) {
        ans.push_back(path[path.size() - 1]);
    }
    ans.push_back(tmp);
    return ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值