UVA10012

来源:互联网 发布:网络兼职吧百度贴吧 编辑:程序博客网 时间:2024/05/16 19:04

题目的意思就是给你几个圆,输入的的半径,排过去长度最小是多少。

先是全排列,得到所有的顺序,然后每个顺序计算长度。

计算长度的方法就是先算出第一个圆的圆心位置(也就是第一个圆的半径) ,然后第二个圆的圆心位置 和第一个圆的圆心位置 相差两圆的半径相乘开更乘以2。当然也可以用两圆半径和的平方 + 两圆半径差的平方 再开更。得到距离在加上第一个个圆的圆心位置就得到第二个的了。算到第n个圆圆心位置。

但要注意以下几点:

1.第n个圆的圆心位置,不一定就是和前一个圆计算得来的。有可能第一个圆很大,第二个圆很小,第三个圆和第一个圆相切,而不碰到第二个圆,所以每个圆要和所有之前的  圆进行计算,取最大值。

2.如果第一个圆很小,第二个圆很大,计算完第二个的圆心位置可能会比半径小,也就是超过了左边边界,这时候它的圆心位置应该变成它的半径。

3.最后就是注意,并不是最后一个圆的圆心位置加上半径,就是所求的长度,有可能前一个特别大,最后一个很小,根本没碰到边界,所以要计算每个圆的圆心位置加半径,取  最大的,才是最后结果。


AC代码:


#include<iostream>#include<cmath>#include<algorithm>#include<string.h>#include<stdio.h>using namespace std;double circle[10];double center[10];int num;double m;double m2;double fina;void search(int pos) {if(pos == num)return ;double temp;m = 0;for (int i = 0 ; i < pos ;i++) {temp = 2 * sqrt (circle[i] * circle[pos] );temp += center[i];if (temp - circle[pos] < 0)temp = circle[pos];if (temp > m) {m = temp;}} center[pos] = m;if (center[pos] + circle[pos] > m2)m2 = center[pos] + circle[pos];search(pos + 1);}void cul () {do {m2 = circle[0] * 2;center[0]= circle[0];search(1);if (m2 < fina) {fina = m2;}}while(next_permutation(circle , circle + num));}int main () {int t;cin >> t;while (t--) {cin >> num;for (int i = 0 ; i < num ; i++) {cin >> circle[i];}sort(circle , circle + num);fina = 9999999999999;if(num != 1)cul();elsefina = circle[0] * 2;printf("%.3lf\n", fina);}}




0 0
原创粉丝点击