POJ 1017 Packets (典型的贪心算法)

地址:http://poj.org/problem?id=1017

翻译:http://poj.grids.cn/practice/1017/

思路:贪心算法 ,  其实这道题的关键就是要解决2*2规格的。处理的时候要注意向上调整

题目分析:有6*6规格的箱子和一大堆木块  用多少箱子可以把木块都装下

先放大的6*6 5*5 4*4 都需要新开箱子 每4个3*3需要开个新箱子  算下剩多少2*2和1*1的  如果不够再开箱子
 
如果一个箱子中放置了一个6*6的产品,则此箱子中无法放置其它产品;
若放置一个5*5的产品,则此箱子中还可放置11个1*1的产品;
若放4*4的产品,还可放5个2*2的产品。
若放置3*3的产品,可以放置4个、3个、2个、1个,剩余的空位分别对应可以放置0个1*1,0个2*2; 5个1*1,1个2*2; 6个1*1,3个2*2; 7个1*1,5个2*2;
若放2*2产品,可放9个;
若放1*1产品,可放36个
 
代码如下:
 1 #include <iostream>
 2 using namespace std;
 3 int main() 
 4 {
 5     int b6,b5,b4,b3,b2,b1; //不同大小的木块个数
 6     int nTotal = 0; //最少需要的箱子数目
 7     int c1; //当前能放 1*1 木块的空格数目
 8     int c2; //当前能放 2*2 木块的空格数目
 9     int Contain2[4] = { 0, 5, 3, 1 }; //记录被3*3的占用之后,还剩多少给2*2的使用  
10     while(1)
11     {
12         cin>>b1>>b2>>b3>>b4>>b5>>b6;//输入1*1到6*6箱子的个数 
13         if (b1 == 0 && b2 == 0 && b3 == 0 && b4 == 0 
14         && b5 == 0 && b6 == 0) break;
15         nTotal = b6 + b5 + b4 + (b3 + 3)/4;   //只能装1个6*6的,1个5*5的,1个4*4的,而3*3的需要多情况考虑,3*3的需要向上调整,你懂的。。。。。
16         //这里有一个小技巧 (b3+3)/4 正好等于b3除以4向上取整的结果,下同 
17         c2 = 5 * b4 + Contain2[b3 % 4];  //放2*2的数目等于放一个4*4时需要5个2*2加上放1到4个3*3时各需要的数目 ,即还可以装多少个2*2的  
18         if(b2 > c2)    nTotal += (b2 - c2 + 8 ) / 9; //向上调整 ,总的2*2的个数减去装过的2*2的个数,得到剩余的2*2的个数,此个数加上8然后除以9就正好等于它除以9向上取整的结果,之所以总数要加上这个数是由于若单独装2*2,可以装9个
19         c1 = 36 * nTotal - 36 * b6 - 25 * b5 - 16 * b4 - 9 * b3 - 4 * b2;  //还可以装多少个1*1的,妙啊!  
20         if(b1 > c1)    nTotal += ( b1 - c1 + 35 ) / 36; //向上调整 ,总的1*1的个数减去装过的1*1的个数,得到剩余的1*1的个数,此个数加上35然后除以36就正好等于它除以36向上取整的结果,之所以总数要加上这个数是由于若单独装1*1,可以装36个
21         cout << nTotal << endl;
22     }
23     return 0;
24 }

 

 参考借鉴代码如下:

 1 #include<iostream>
 2 using namespace std;
 3 int pk[7];
 4 int pk3[4]={0,5,3,1}; //记录被3*3的占用之后,还剩多少给2*2的使用
 5 int main()
 6 {
 7     int i;
 8     bool flag;
 9     for(i=1;i<=6;i++)
10     {
11         scanf("%d",&pk[i]);
12         if(pk[i])
13             flag=true;
14     }
15     while(flag)
16     {
17         int sum=0;
18         flag=false;
19         sum=pk[4]+pk[5]+pk[6]+(pk[3]+3)/4;//向上调整
20         int left2=pk[4]*5+pk3[pk[3]%4];   //还可以装多少个2*2的 
21         if(left2<pk[2])
22             sum+=(pk[2]-left2+8)/9;//向上调整
23         int left1=sum*36-pk[2]*4-pk[3]*9-pk[4]*16-pk[5]*25-pk[6]*36; //还可以装多少个1*1的,妙啊!
24         if(left1<pk[1])
25             sum+=(pk[1]-left1+35)/36;//向上调整
26         printf("%d/n",sum);
27         for(i=1;i<=6;i++)
28         {
29         scanf("%d",&pk[i]);
30             if(pk[i])
31                 flag=true;
32         }
33 
34     }
35     return 0;
36 }

 

 

posted on 2012-08-23 11:01  mycapple  阅读(1229)  评论(0编辑  收藏  举报

导航