枚举法 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;
}