poj 1411(搜索+剪枝)

          题目链接:http://poj.org/problem?id=1411

       本来是自己写的,但是一直超时,一时也想不到好的剪枝方法,就去网上找了找,主要内容转载自一下链接:

         http://blog.sina.com.cn/s/blog_6a98ae6c0100les3.html

         分析:

1.读题,看懂题意。
2.分析题意,把问题抽象化。
3.获取有用信息
    a.给定整数m,a,b(4 < m <= 100000 and 1 <= a <= b <= 1000)
    b.需要找到两个数(不妨设为p,q)满足以下条件:
    p,q均为质数;
    p*q<=m;
    a/b <= p/q <= 1;

c.输出所有满足以上条件的p,q中乘积最大的一对p,q

思路分析:

1.典型的搜索
   从所有可能的p,q中寻找满足条件的一对
2.p,q的要求
   p,q均为质数,且p<=q<=100000;
3.按上述思想流程应为
   a.从1—100000中搜出质数
   b.两层循环,试遍所有的组合(p,q可能相等)
   c.每种组合去判断是否符合条件,如是,将p*q与当前最大值比较,判断,保存

4.面临的问题:
    超时!
    从1—100000的质数运算约为1e+8,而这只是准备工作。
    因此,如不加以分析简化此题无法在规定时间内出解
5.深入分析
   p,q的范围其实可在2—50000(why?)
   (事实上,很多通过的程序就采取的事这种思路,然而这是最小的范围吗?)

考虑9091这个数
   2/9091=0.00022
   3/9091=0.00033
   5/9091=0.00055
   7/9091=0.00077
   而考虑到a,b的取值范围(1<=a<=b<=1000)
   可知min(a/b)=0.001
   所以2,3,5,7均不能作为p.
   min(p)=11;
   而11*9091=100001>100000;
   所以无论如何9091都不能作为q

而超过9091的数则更不可能。
所以p,q只能在2—9091中取值,从而使问题大大简化。

代码:

#include<stdio.h>
int prime1[10000]={0};
int prime[20000];
int count,max;
int m,a,b;
int ans1,ans2;
void getprime()
{
	int i,j;
	prime1[0]=1;
	prime1[1]=1;
	for(i=2;i<=5000;i++)
	{
		if(!prime1[i])
		{
			for(j=2;i*j<=10000;j++)
			{
                  prime1[i*j] = 1;
			}
		}
	}
	count=-1;
	for(i=0;i<10000;i++)
	    if(prime1[i] == 0)
		{
			++count;
			prime[count]=i;
		}
	
}
int main()
{
	int i,j;
	getprime();
	while(1)
	{
		scanf("%d%d%d",&m,&a,&b);
	    if(m==0 && a==0 && b==0)
			break;
		max=0;
        for(i=count;i>=0;i--)
		{
		    if(prime[i]>m)continue;	
			for(j=i;j<=count;j++)
			{
				if(prime[j]>m || prime[i]*prime[j]>m || (double)prime[i]/prime[j] < (double)a/b)break;
				if(prime[i]*prime[j] > max)
				{
					max=prime[i]*prime[j];
					ans1=prime[i];
					ans2=prime[j];
				}
			}
		}
		printf("%d %d\n",ans1,ans2);
	}
	return 0;
}



 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值