ACM气球膨胀问题C++实现

本文探讨了在一个矩形区域内,以三个固定点为中心的气球依次膨胀的问题,并通过穷举法确定气球的最佳膨胀顺序,以使得这些气球的横切面面积之和达到最大。文中提供了一个C++实现的示例程序。
1.问题描述:
给定一个矩形,在该矩形中有3个固定的点,以这3个点为中心的气球先后膨胀:膨胀时触碰到矩形的边或其他气球时则停止膨胀。编写程序求以何种顺序膨胀气球时,才能使气球的横切面面积之和为最大。


解:

(1)以矩形左下角为原点,建立直角坐标系,程序输入的参数为:三个固定点的坐标,矩形的长和宽,输出膨胀顺序;

(2)程序对参数的初步处理是算得三点相互之间的距离以及三点分别与矩形的最近距离,然后穷举法列举所有的膨胀顺序,找到使三个圆半径的平方和最小的膨胀顺序;


C++函数实现及测试:

//
//  main.cpp
//  C++
//
//  Created by Xinhou Jiang on 6/11/16.
//  Copyright © 2016 Xinhou Jiang. All rights reserved.
//
#include <iostream>
#include <math.h>
using namespace std;
//气球膨胀问题
//判断三者最小者函数
double min(double a,double b,double c)
{
    double min=a;
    if(b<a)
        min=b;
    if(c<a)
        min=c;
    return min;
}
//处理气球膨胀函数
void sortBall(double width,double height,double xA,double yA,double xB,double yB,double xC,double yC)
{
    //点与点之间的距离
    double distance[3];
    distance[0]=sqrt(pow((xA-xB),2)+pow((yA-yB),2));
    distance[1]=sqrt(pow((xA-xC),2)+pow((yA-yC),2));
    distance[2]=sqrt(pow((xC-xB),2)+pow((yC-yB),2));
    //点与矩形的最近距离
    double minRect[3];
    double minA_x=xA>width/2?(width-xA):xA;
    double minA_y=yA>height/2?(height-yA):yA;
    minRect[0]=minA_x;
    double minB_x=xB>width/2?(width-xB):xB;
    double minB_y=yB>height/2?(height-yB):yB;
    minRect[1]=minB_x;
    double minC_x=xC>width/2?(width-xC):xC;
    double minC_y=yC>height/2?(height-yC):yC;
    minRect[2]=minC_x;
    int relative[3][2]={0,1,0,2,1,2};
    bool stat[3]={true,true,true};//初始化三个气球状态都未膨胀
    int array[3];//临时顺序
    int terarray[3];//气球膨胀最终顺序
    double rad[3];//膨胀后的气球半径
    double powrad2=0;//半径平方和
    
    //开始穷举
    for(int i=0;i<3;i++)
    {//第一个膨胀的气球
        stat[i]=false;
        rad[i]=min(minRect[i],distance[relative[i][0]],distance[relative[i][1]]);//第一个膨胀的气球的半径
        distance[relative[i][0]]-=rad[i];
        distance[relative[i][1]]-=rad[i];
        array[0]=i+1;//第一个膨胀的气球编号
        for(int j=0;j<3;j++)
        {//第二个膨胀的气球
            if(stat[j])
            {
                stat[j]=false;
                rad[j]=min(minRect[j],distance[relative[j][0]],distance[relative[j][1]]);//第二个膨胀的气球的半径
                distance[relative[j][0]]-=rad[j];
                distance[relative[j][1]]-=rad[j];
                array[1]=j+1;//第二个膨胀的气球编号
                for(int k=0;k<3;k++)
                {//第三个膨胀的气球
                    if(stat[k])
                    {
                        rad[k]=min(minRect[k],distance[relative[k][0]],distance[relative[k][1]]);//第三个膨胀的气球的半径
                        array[2]=k+1;//第三个膨胀的气球编号
                        if((pow(rad[0],2)+pow(rad[1],2)+pow(rad[2],2))>powrad2)
                        {
                            powrad2=(pow(rad[0],2)+pow(rad[1],2)+pow(rad[2],2));
                            terarray[0]=array[0];
                            terarray[1]=array[1];
                            terarray[2]=array[2];
                        }
                        cout<<array[0]<<endl;
                        cout<<array[1]<<endl;
                        cout<<array[2]<<endl;
                        cout<<"-------------------"<<endl;
                    }
                }//第三个膨胀的气球
                //恢复第二个气球初始状态
                //点与点之间的距离
                distance[relative[j][0]]+=rad[j];
                distance[relative[j][1]]+=rad[j];
                stat[j]=true;//恢复第二个气球状态都未膨胀
            }
        }//第二个膨胀的气球
        //恢复初始状态
        //点与点之间的距离
        distance[0]=sqrt(pow(xA-xB,2)+pow(yA-yB,2));
        distance[1]=sqrt(pow(xA-xC,2)+pow(yA-yC,2));
        distance[2]=sqrt(pow(xC-xB,2)+pow(yC-yB,2));
        stat[0]=true;//恢复三个气球状态都未膨胀
        stat[1]=true;
        stat[2]=true;
    }//第一个膨胀的气球
    cout<<"最佳膨胀顺序为:"<<terarray[0]<<"-"<<terarray[1]<<"-"<<terarray[2]<<endl;
}
//主函数测试
int main()
{
    sortBall(20,10,3,5,4,2,8,5.5);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_厚厚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值