写C语言代码实现:给定n个圆的整数半径序列,将这些圆放到一个矩形框中,每个圆都与矩形框的底边相切,则圆的不同排列会得到不同的排列长度,如下图: 1.jpg 注意:因为圆的半径可能很大,也可能很小,也许会有这种情况出现: 2.jpg 要求找到使得排列长度最小的n个圆的排列。 输入格式: 第一行输入n值(1≤n≤10)。 第二行输入n个圆的整数半径序列。 输出格式: 第一行输出最小的排列长度,精确到小数点后两位,第三位按四舍五入方式处理。 第二行输出该排列对应的半径序列,各半径之间用一个空格分隔。为方便处理,最末位半径后面存在一个空格。 输入样例1: 3 3 3 3 输出样例1: 18.00 1 2 3 输入样例2: 5 1 3 5 7 9 输出样例2: 44.97 1 4 2 5 3
时间: 2024-03-26 17:35:46 浏览: 88
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define MAX_N 10
// 圆结构体
typedef struct Circle {
int r; // 半径
int x; // 圆心横坐标
int y; // 圆心纵坐标
} Circle;
// 矩形结构体
typedef struct Rectangle {
int w; // 矩形宽度
int h; // 矩形高度
} Rectangle;
// 计算两个圆的切点
bool get_tangent_points(Circle c1, Circle c2, Circle* p1, Circle* p2) {
int d = sqrt(pow(c2.x - c1.x, 2) + pow(c2.y - c1.y, 2)); // 圆心距离
if (d < c1.r + c2.r) { // 两圆相交
return false;
}
double sin_alpha = (double)(c2.y - c1.y) / d; // sin alpha
double cos_alpha = (double)(c2.x - c1.x) / d; // cos alpha
double sin_beta = (double)c1.r / d; // sin beta
double cos_beta = (double)c2.r / d; // cos beta
double sin_theta = sin_alpha * cos_beta - cos_alpha * sin_beta; // sin theta
double cos_theta = cos_alpha * cos_beta + sin_alpha * sin_beta; // cos theta
p1->x = c1.x + c1.r * cos_theta;
p1->y = c1.y + c1.r * sin_theta;
p2->x = c2.x - c2.r * cos_theta;
p2->y = c2.y - c2.r * sin_theta;
return true;
}
// 计算圆与矩形的交点
bool get_intersection_point(Circle c, Rectangle r, Circle* p1, Circle* p2) {
if (c.x - c.r < 0 || c.x + c.r > r.w || c.y - c.r < 0) { // 圆超出矩形
return false;
}
p1->x = c.x;
p1->y = c.y;
p2->x = c.x;
p2->y = r.h;
return true;
}
// 计算排列长度
double get_permutation_length(Circle* circles, int n) {
double length = 0;
for (int i = 1; i < n; i++) {
Circle p1, p2;
bool has_tangent_points = false;
for (int j = i - 1; j >= 0; j--) {
Circle t1, t2, p3, p4;
if (get_tangent_points(circles[i], circles[j], &t1, &t2)) {
if (!has_tangent_points) {
p1 = t1;
p2 = t2;
has_tangent_points = true;
} else {
double d1 = sqrt(pow(t1.x - p2.x, 2) + pow(t1.y - p2.y, 2));
double d2 = sqrt(pow(t2.x - p1.x, 2) + pow(t2.y - p1.y, 2));
if (d1 < d2) {
p1 = t1;
p2 = p2;
} else {
p1 = p1;
p2 = t2;
}
}
}
if (get_intersection_point(circles[i], (Rectangle){p2.x - p1.x, p2.y}, &p3, &p4)) {
if (!has_tangent_points) {
p1 = p3;
p2 = p4;
has_tangent_points = true;
} else {
double d1 = sqrt(pow(p3.x - p2.x, 2) + pow(p3.y - p2.y, 2));
double d2 = sqrt(pow(p4.x - p1.x, 2) + pow(p4.y - p1.y, 2));
if (d1 < d2) {
p1 = p3;
p2 = p2;
} else {
p1 = p1;
p2 = p4;
}
}
}
}
length += sqrt(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2)) + 2 * circles[i].r;
}
return length;
}
// 交换两个圆
void swap(Circle* c1, Circle* c2) {
Circle tmp = *c1;
*c1 = *c2;
*c2 = tmp;
}
// 全排列
void permutation(Circle* circles, int n, int i, double* min_length, Circle* min_circles) {
if (i == n) {
double length = get_permutation_length(circles, n);
if (length < *min_length) {
*min_length = length;
for (int j = 0; j < n; j++) {
min_circles[j] = circles[j];
}
}
} else {
for (int j = i; j < n; j++) {
swap(&circles[i], &circles[j]);
permutation(circles, n, i + 1, min_length, min_circles);
swap(&circles[i], &circles[j]);
}
}
}
int main() {
int n;
scanf("%d", &n);
Circle circles[MAX_N];
for (int i = 0; i < n; i++) {
scanf("%d", &circles[i].r);
circles[i].x = 0;
circles[i].y = circles[i].r;
}
double min_length = INFINITY;
Circle min_circles[MAX_N];
permutation(circles, n, 0, &min_length, min_circles);
printf("%.2f ", min_length);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (circles[j].r == min_circles[i].r) {
printf("%d ", j + 1);
break;
}
}
}
putchar(' ');
return 0;
}
```
阅读全文