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 }