POJ 1017 Packets

POJ 1017题目大意如下:
有1*1、2*2、3*3、4*4、5*5、6*6这六种型号的包装盒,也指定了相对于这六种型号的产品的分别的数量。由于物流运送费用是和运送商品的数量成正比的(商品运送的时候是包装在包装盒里的),为了节省物流开支,需要确定一种最佳的包装方案,即:使用最少数量的包装盒。
简单的贪心,具体分析如下:
1)都使用6*6的包装盒;
2)如果一个包装盒里包装的是6*6的商品,那么这个包装盒就不能再装其他商品了;
3)如果一个包装盒里包装的是5*5的商品,那么这个包装盒就只能装1*1的商品11个;
4)如果一个包装盒里包装的是4*4的商品,那么这个包装盒就只能装2*2的商品或者1*1的商品了,然而这种情况我们得仔细分析一下:首先知道一个6*6的盒子可以装入4个3*3的商品,向上取整(count3 + 3) / 4 就得到3*3所需的所有盒子数目。对于未装满的6*6的盒子,我们需要对于三种情况分别作分析:
i)如果装入1个3*3的商品,那么可以装入的2*2的盒子数为5,剩余可以装入7个1*1;
ii)如果装入2个3*3的商品,那么可以装入的2*2的盒子数为3,剩余可以装入6个1*1;
iii)如果装入3个3*3的商品,那么可以装入的2*2的盒子数为1,剩余可以装入5个1*1;
假设temp是装入的3*3的数目,count2为2*2的数目,count1为1*1的数目,有下面函数关系:
count2 = 7 - 2*temp
count1 = 8 - temp

5)当确定了这些之后,余下的工作就是往3*3~5*5的盒子里填充1*1或者2*2的盒子;
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>

using namespace std;
int a[7];
int b[] = {0, 5, 3, 1, 0};

void solve() {
    int sum = a[6] + a[5] + a[4] + (a[3] + 3) / 4;
    //先填充5*5的剩余空间
    a[1] = max(0, a[1] - 11*a[5]);
    if (a[2] > a[4]*5) a[2] -= a[4]*5;
    else {
        a[1] = max(0, a[1] - 4*(a[4]*5 - a[2]));
        a[2] = 0;
    }
    //找出3*3没有填满的箱子有多少3*3的箱子
    int temp = a[3] % 4;
    if (temp) {
        if (a[2] > 7 - 2*temp) {
            a[2] -= 7 - 2*temp;//尽可能填满2*2,根据剩余temp的关系:temp={1,2,3}, count={5,3,1}
            a[1] = max(0, a[1] - (8 - temp));//尽可能填满1*1,同样有关系:count={7,6,5}
        }
        else {
            a[1] = max(0, a[1] - 36 + temp*9 + a[2]*4);//尽量放1*1的
            a[2] = 0;
        }
    }
    sum += (a[2] + 8) / 9;
    if (a[2] % 9) a[1] = max(0, a[1] - 36 + (a[2] % 9)*4);
    sum += (a[1] + 35) / 36;
    printf("%d\n", sum);
}

int main(int argc, const char * argv[]) {
    // insert code here...
    while(true) {
        int flag = false;
        for (int i = 1; i <= 6; i++) {
            scanf("%d", &a[i]);
            if (a[i]) flag = true;
        }
        if (!flag) break;
        solve();
    }
    return 0;
}


你可能感兴趣的:(ACM,poj,ICPC,暴力,穷竭)