poj 1017 艰难的一个AC 贪心算法

#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;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

apple_51426592

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值