poj1855(Mint)

来源:互联网 发布:office2003是什么软件 编辑:程序博客网 时间:2024/06/11 00:49

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

       题目大意:有n种厚度不同硬币,现在要使用这n种硬币中的四种堆成一张桌子的四个脚,每个脚只能由一种硬币组成,现有t张桌子,已知每张桌子桌脚的高度,现在要你组成最接近这个高度的的高度,输出一个最接近该高度但又小于该高度的最大值和一个最接近该高度的但又大于该高度的最小值。

       思路:由于桌子的四个脚由四种厚度不同的硬币组成,但最后的高度是相同的,所以该高度肯定是这四种硬币厚度的最小公倍数的n倍。因此只需找出所有组合的最小公倍数,然后进行比较即可!!用了4重for循环,没做之前都担心超时啊,没想最后通过的时间是172ms,是不是有点坑我啊!!!!

代码:

#include<stdio.h>int types[60];int tables[15];int n,t;int maxans[15],minans[15];int gcd(int x,int y)//求最大公约数{int temp,t;if(y>x){       temp=x;   x=y;   y=temp;}while(y!=0){t=x%y;x=y;y=t;}return x;}int lcm(int a,int b)//求最小公倍数{return (a*b)/gcd(a,b);}void solve(int lcd1){int i;int temp;int tempmaxans,tempminans;for(i=0;i<t;i++){          if(tables[i]%lcd1 == 0)  {  maxans[i]=tables[i];  minans[i]=tables[i];  }  else  {  temp=(int)(tables[i]/lcd1);  tempmaxans=lcd1*temp;  tempminans=lcd1*(temp+1);              if(tempmaxans > maxans[i])  maxans[i]=tempmaxans;  if(tempminans < minans[i])  minans[i]=tempminans;  }}}int main(){int i,j,k,l;int lcd,templcd1,templcd2;while(1){scanf("%d%d",&n,&t);if(n==0 && t==0)break;for(i=0;i<n;i++)scanf("%d",&types[i]);for(i=0;i<t;i++){scanf("%d",&tables[i]);            maxans[i]=0;minans[i]=200000000;}for(i=0;i<n-3;i++)//循环求出所有组合的最小公倍数{for(j=i+1;j<n-2;j++){templcd1=lcm(types[i],types[j]);for(k=j+1;k<n-1;k++){templcd2=lcm(templcd1,types[k]);for(l=k+1;l<n;l++){                         lcd=lcm(templcd2,types[l]); solve(lcd);//判断当前最小公倍数是否能影响结果}}}}     for(i=0;i<t;i++) printf("%d %d\n",maxans[i],minans[i]);   }return 0;}