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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值