#include<iostream> #include<fstream> using namespace std; int countBox; int count1Dot1; int count2Dot2; int Cal(int array[]) { int i,j,k; for(i=6;i>=1;i--) { switch(i) { case 6: { countBox+=array[6]; break; } case 5: { countBox+=array[5]; count1Dot1+=array[5]*11; break; } case 4: { countBox+=array[4]; count2Dot2+=array[4]*5; break; } case 3: { j=array[3]%4; k=array[3]/4+1;//向上取整 switch(j) { case 0: { countBox+=(array[3]/4); break; } case 1: { countBox+=k; count1Dot1+=7; count2Dot2+=5; break; } case 2: { countBox+=k; count1Dot1+=6; count2Dot2+=3; break; } case 3: { countBox+=k; count1Dot1+=5; count2Dot2+=1; break; } } break; } case 2: { if(array[2]<=count2Dot2) { count2Dot2-=array[2]; count1Dot1+=(4*count2Dot2);//剩余的2*2记得转为1*1 count2Dot2=0; } else { int Much=array[2]-count2Dot2;//剩余多少2*2 int t=Much/9;//6*6可以有9个2*2个箱子向上取整 if(Much%9!=0)//向上取整 { t++; count1Dot1+=((9-Much%9)*4); } countBox+=t; } break; } case 1: { if(array[1]<=count1Dot1) { count1Dot1-=array[1];} else { int Much=array[1]-count1Dot1; int t=Much/36; if(Much%36!=0) t++; countBox+=t; count1Dot1+=(Much%36); } break; } } } return countBox; } int main() { int array1[7]; int num0=0; while(true) { num0=0; for(int i=1;i<=6;i++) { scanf("%d",&array1[i]);} for(int i=1;i<=6;i++) { if(array1[i]==0) num0++; } if(6==num0) { break;} int k=Cal(array1); printf("%d\n",k); countBox=0; count1Dot1=0; count2Dot2=0; } }
AC过的代码,尚未优化,题目的思路,下面再讲,先上代码。
求解问题的思路:
贪心算法:先放大件,再放小件。
int countBox;//统计需要的箱子数
int count1Dot1;//统计空余的1*1数
int count2Dot2;//统计空闲的2*2数
具体说明如下:
6*6:需要占用一个箱子
5*5:占用一个箱子 余11个 1*1
4*4:占用一个箱子,余5个2*2
3*3:
若4*n+1:余5个2*2,7个1*1
若4*n+2余3个2*2,6个1*1
若4*n+3余1个2*2,5个1*1
用swich语句,从6*6处理到1*1;
注意实现:向上取整,直接可以用统一表达式:
int Need=(array[1]-count1Dot1+35)/36;//向上取整的办法;
未优化的向上取整,采用
int Much=array[1]-count1Dot1; int t=Much/36; if(Much%36!=0) t++; countBox+=t; count1Dot1+=(Much%36);
显得过于累赘,容易出错。
统计1*1空闲位置的表达式采用:
count1Dot1=countBox*36-array[6]*36-array[5]*25-array[4]*16-array[3]*9-array[2]*4;//计算空闲1*1空间。
未优化的方法,计算该值过于繁琐。
程序容易出现错误的地方是:
countBox=0;
count1Dot1=0;
count2Dot2=0;
每组数据处理完之后,忘记进行初始化。
该POJ:非常容易出错,必须进行大量的数据测试过后,才可以保证争取,样例只有两个例子,命令过少。
我采用1000个数据进行测试,最终修改过很多次,才AC了。
经验:有时候,测试样例没问题,但就是Wrong Answer,那说明你的程序逻辑有问题,对某些测试数据不行。
解决方法:
网上寻找测试数据,进行测试,跟能够AC过的程序进行对比,可以观察两个程序运行过程中的中间变量等等。
http://poj.org/showmessage?message_id=111906附有本题的测试数据
#include<iostream> //****************算法变量********************* int countBox;//统计需要的箱子数 int count1Dot1;//统计空余的1*1数 int count2Dot2;//统计空闲的2*2数 //****************题目变量********************* int input[7];//输入数组 int Cal(int array[]) { int i,j,k; for(i=6;i>=1;i--) { switch(i) { case 6: countBox+=array[6]; break; case 5: countBox+=array[5]; break; case 4: countBox+=array[4]; count2Dot2+=array[4]*5; break; case 3: j=array[3]%4; k=(array[3]+3)/4;//向上取整 switch(j) { case 0: countBox+=k; break; case 1: countBox+=k; count2Dot2+=5; break; case 2: countBox+=k; count2Dot2+=3; break; case 3: countBox+=k; count2Dot2+=1; break; } break; case 2: if(array[2]<=count2Dot2) count2Dot2-=array[2]; else { int Need=(array[2]-count2Dot2+8)/9;// countBox+=Need; } break; case 1: { count1Dot1=countBox*36-array[6]*36-array[5]*25-array[4]*16-array[3]*9-array[2]*4;//计算空闲1*1空间 if(array[1]<=count1Dot1) { count1Dot1-=array[1];} else { int Need=(array[1]-count1Dot1+35)/36;//向上取整的办法 countBox+=Need; } break; } } } return countBox; } int main() { int num0=0; while(true) { num0=0; for(int i=1;i<=6;i++) { scanf("%d",&input[i]);} for(int i=1;i<=6;i++) { if(input[i]==0) num0++; } if(6==num0) { break;} int k=Cal(input); printf("%d\n",k); countBox=0; count1Dot1=0; count2Dot2=0; } }