枚举法 POJ1411

给3个数 m ,a,b, 求两个素数 c和d,

使得 c*d<=m a/b<=c/d<=1

其中m>4, a/b<=1

思路

穷举素数 c(1,3,5,7,9,….m) c的穷举范围为(0,m)中所有的素数。

对于每一个穷举的c,根据e=c*b/a,确定d的范围为 (c,e)之间 的素数,

再在c确定的情况下,在d的范围(c,e)之中寻找一个素数使得c*d的面积最大,并且c*d<=m;

通过程序

#include <math.h>

#include<iostream>

#include <algorithm>

#include <cstdio>

//判断是否是质数

bool isPrime(int t)

{

int mid =(int)(sqrt((double)t));

for(int i=2;i<=mid;i++)

if(t%i==0)

return false;

return true;

}

/*

给3个数 m ,a,b, 求两个素数 c和d,

使得 c*d<=m a/b<=c/d<=1

其中m>4, a/b<=1

第一次审题后的解法

穷举素数 c(1,3,5,7,9,….m) c的穷举范围为(0,m)中所有的素数。

对于每一个穷举的c,根据e=c*b/a,确定d的范围为 (c,e)之间的素数,再在c确定的情况下,在d的范围(c,e)之中寻找一个素数使得c*d的面积最大,并且c*d<=m;

枚举的优化策略

改变枚举次序

改变比较情况时所花的时间

剪枝--减少边界条件的枚举情况.

在本例中可以优化的地方为 确定p和q的取值范围,

对于确定的m,p和q为质数,所以p和q最多取到sqrt(m);

因为m<=100000, sqrt(100000)=316.999,

所以p和q最多取到317

*/

int main(void)

{

int m,a,b,c,tt,temp,width,height;

double d,e,min;

long tempm,max;

while(1)

{

std::cin>>m>>a>>b;

if(m==0)break;

max=0;

/*

因为m的最大值为100000,所以可以确定在a=b的情况下,width和height的最大值最多为317,所以可以减少遍历时间

*/

for(c=2;c<=317;c++)

{

if(isPrime(c)==true)

{

//e的取值为 min(m/c,c*b/a)

e=((double)c*b)/a;

min=m/c;

if(min<e)e=min;

for(tt=e;tt>=c;tt--) //确定c的范围后在c到E之间找一个最大的质数,使其满足条件c*tt<=m,对于tt为从大到小开始遍历

{

if(isPrime(tt))

{

tempm=c*tt;

if(tempm<=m&&tempm>max)

{

width=c;

height=tt;

max=tempm;

break;

}

}

}

}

}

std::cout<<width<<" "<<height<<std::endl;

}

return 0;

}

posted @ 2010-03-10 22:42  smile2you  阅读(569)  评论(0编辑  收藏  举报