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;
}