已知矩形体积,求解最小表面积(优化算法)

题是51nod上的 3330 Minecraft题目地址(网站崩了就去按题号找一下)

输入一个n,n<=1e9,n是小方块个数,可以相当于已知矩形体积,求解最小表面积的长宽高为整数的解。

首先因为n的范围很大,不能用三重循环的做法,就是分别遍历长宽高,然后满足条件算出表面积维护最小值。
最简单的优化是把三重循环变成二重循环,参考poj 2363 ,相当于用体积公式去掉一重循环,已知长宽可以由V=abc得a=V/(b*c),然后同上,满足条件算出表面积维护最小值。

接下来就是能ac的思路了,第一步先求出n的所有质因数,就是不断除以2,除到不能除为止看能不能除以3、5、7…
第二步是把这些质因数存到动态数组里,分为五种情况,一是动态数组里没有值,这种情况只能是n=1,由表面积计算公式得s=6,输出即可;二是动态数组有唯一值,三是动态数组有唯二值,四是动态数组有唯三值,把值赋给矩形的边,剩下的补1,由表面积公式求出即可;五是动态数组中的值大于三个,由规律可知最大的质因数一定是矩形的其中一个边,然后不断改变矩形的其它两边(由不等式定理知三边最接近时表面积最小)(可理解为三边相减的绝对值最小的时候表面积最小)然后通过更新两条边的值算出绝对值相减最小的时候并记录三条边的值。ans为求出的最小表面积的结果。

#include<iostream>
#include<set>
#include<queue>
#include<cmath>
#include<stack>
#include<vector>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=1e6+5;
typedef long long ll;
vector<ll> ve;
ll ans=0x3f3f3f3f;
int judge(ll a,ll b,ll c){
    if(b<c){
        ll temp=b;
        b=c;
        c=temp;
    }
    return (a-c)+(a-b)+(b-c);
}
void solve(){
    ll a,b,c=1;
    ll min=0x3f3f3f3f;//三边维护值最小(绝对值)
    a=ve[ve.size()-1];//一定是个大质因数,它不变,但是三边维护要用它
    b=ve[ve.size()-2];
    for(int i=0;i<ve.size()-2;i++){
        c*=ve[i];
    }
    ll bb=b,cc=c;
    int t=0;
    while(true){
        if(min>judge(a,b,c)){
            min=judge(a,b,c);
            bb=b;
            cc=c;
        }
        b*=ve[t];
        c/=ve[t];
        if(t==ve.size()-3) break;
        else t++;
    }
    ans=2*(a*bb+a*cc+bb*cc);
}
int main(){
    ll n;
    cin>>n;
    while(n%2==0){
        ve.push_back(2);
        n/=2;
    }
    for(int i=3;i<=sqrt(n*1.0);i+=2){
        while(n%i==0){
            ve.push_back(i);
            n/=i;
        }
    }
    if(n>2){
        ve.push_back(n);
    }
    int len=ve.size();
    if(len==0) ans=6;
    else if(len==1) ans=ve[0]*4+2;
    else if(len==2) ans=2*(ve[0]*ve[1]+ve[0]+ve[1]);
    else if(len==3) ans=2*(ve[0]*ve[1]+ve[0]*ve[2]+ve[1]*ve[2]);
    else{
        //找到三个边,三边维护绝对值差最小
        solve();
    }
    cout<<ans<<endl;
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值