POJ 1017 Packets

 嗯一天了还没有发一篇有意义的文章
就算博客没人看也觉得不好意思了
其实一直在研究Syntax Highlighter核心代码...
而且博皮没搞好还不好意思上来秀智商...

此题是平面内的, 不是立体的, 被坑了好久...(没错那个在POJ发了Discuss的就是本人)
然后我前半夜在分析样例上(我用立体的来分析...然后搞了好久)
后半夜时间浪费在压代码, 优化上, 以及解决优化之后出现的各种神奇bugs

下面是代码, 可能不好懂, 分析见下面的下面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <cstdio>
using namespace std;
 
int a, b, c, d, e, f, x;
int u[4] = { 0, 5, 3, 1 };
int v[4] = { 0, 7, 6, 5 };
 
int main() {
    while (~scanf("%d%d%d%d%d%d", &a, &b, &c, &d, &e, &f)) {
        if (!a && !b && !c && !d && !e && !f) break;
        x = f + e + d + (c + 3) / 4;
        if ((b -= 5 * d + u[c & 3]) > 0) x += (b + 8) / 9, b = (b % 9 - 9) % 9;
        if ((a -= 11 * e + v[c & 3] - b * 4) > 0) x += (a + 35) / 36;
        printf("%d ", x);
    }
    return 0;
}

以下是代码分析...如果还有什么不懂欢迎提问

觉得x=f+e+d+(c+3)/4;没什么好解释吧
每个6*6, 5*5需要增加一个包装, 每4个3*3需要一个包装

能塞就塞, 先塞大的这个不需要解释吧, 很好证明的
第一个反证法搞搞, 第二个就是反正每个包裹早晚都要塞进去而我们为了方便先塞大的

对于每个5*5可以另外塞入11个1*1
对于每个4*4最多可以另外塞入5个2*2
2*2不够怎么办? 我们可以先"借"来足够的, 最后由4个1*1拼接而成
就是先可以用负数表示, 最后的时候一股脑*4加到1*1的个数里面(其实就是不要管它...)

比较讨厌的是3*3的判断
如果3*3的多出1个, 2*2最多可以塞入5个, 多出9个空位1*1塞入
如果3*3的多出2个, 2*2最多可以塞入3个, 多出7个空位1*1塞入
如果3*3的多出3个, 2*2最多可以塞入1个, 多出5个空位1*1塞入
此处同理2*2不够先不用管它, 1*1不够也不管

然后对于2*2自己, 我们先减去所有借来的, 判断一下有没有多余
如果有多余的话, 先能装的全部打包, 零头再借来足够的2*2打包

对1*1而言, 每个5*5会用去11个, 要填上3*3的空位还要还清2*2的债(如果有的话)
如果仍然有剩余的1*1, 直接36个一包一起打包
1*1不够怎么办, 这说明本来就没法塞满, 那就让它空着, 假装它是满的, 反正对结果无影响

转载什么的随便啦, 反正这里没有人气, 有人转载我还高兴...
不过如果真有人转载的话, 希望注明转自此处, 不嫌麻烦就留个言吧, 我也希望这里能热闹起来, thx

原文地址:https://www.cnblogs.com/johnsonyip/p/4298659.html