From 714f9830be77486c32e9f093dde52558bcae8295 Mon Sep 17 00:00:00 2001 From: Zengtudor Date: Wed, 16 Jul 2025 08:56:08 +0800 Subject: [PATCH] update --- src/7/16/Area0.in | 2 + src/7/16/Area0.out | 1 + src/7/16/Area1.in | 2 + src/7/16/Area1.out | 1 + src/7/16/Area2.in | 2 + src/7/16/Area2.out | 1 + src/7/16/T633664.md | 106 ++++++++++++++++++++++++++++++++++++++++++ src/7/16/T633664f.cpp | 49 +++++++++++++++++++ 8 files changed, 164 insertions(+) create mode 100644 src/7/16/Area0.in create mode 100644 src/7/16/Area0.out create mode 100644 src/7/16/Area1.in create mode 100644 src/7/16/Area1.out create mode 100644 src/7/16/Area2.in create mode 100644 src/7/16/Area2.out create mode 100644 src/7/16/T633664.md create mode 100644 src/7/16/T633664f.cpp diff --git a/src/7/16/Area0.in b/src/7/16/Area0.in new file mode 100644 index 0000000..aea8665 --- /dev/null +++ b/src/7/16/Area0.in @@ -0,0 +1,2 @@ +4 +5 6 7 10 \ No newline at end of file diff --git a/src/7/16/Area0.out b/src/7/16/Area0.out new file mode 100644 index 0000000..29ddae2 --- /dev/null +++ b/src/7/16/Area0.out @@ -0,0 +1 @@ +3394819 \ No newline at end of file diff --git a/src/7/16/Area1.in b/src/7/16/Area1.in new file mode 100644 index 0000000..98d3062 --- /dev/null +++ b/src/7/16/Area1.in @@ -0,0 +1,2 @@ +5 +18 4 17 5 1 \ No newline at end of file diff --git a/src/7/16/Area1.out b/src/7/16/Area1.out new file mode 100644 index 0000000..634d987 --- /dev/null +++ b/src/7/16/Area1.out @@ -0,0 +1 @@ +15579794 diff --git a/src/7/16/Area2.in b/src/7/16/Area2.in new file mode 100644 index 0000000..c7207c6 --- /dev/null +++ b/src/7/16/Area2.in @@ -0,0 +1,2 @@ +10 +10 18 12 2 14 17 6 12 7 10 \ No newline at end of file diff --git a/src/7/16/Area2.out b/src/7/16/Area2.out new file mode 100644 index 0000000..938c9b3 --- /dev/null +++ b/src/7/16/Area2.out @@ -0,0 +1 @@ +454559413 diff --git a/src/7/16/T633664.md b/src/7/16/T633664.md new file mode 100644 index 0000000..fd26427 --- /dev/null +++ b/src/7/16/T633664.md @@ -0,0 +1,106 @@ +### 解题思路 +这道题要求使用所有围栏(由不同板材拼接而成)构建一个三角形广场,并最大化三角形面积。围栏的总长度是固定的,为 \( T \)。三角形的三条边由围栏分组拼接而成,每条边的长度必须严格小于 \( T/2 \) 才能满足三角形条件(任意两边之和大于第三边)。问题转化为将围栏分成三组,使得每组和都小于 \( T/2 \),并计算最大可能的三角形面积。 + +### 算法步骤 +1. **计算围栏长度**:遍历所有不同板材对,计算围栏长度 \( S_i + S_j \)(\( i \neq j \)),存储到数组 `lengths` 中。 +2. **计算总长度 \( T \)**:对所有围栏长度求和,或通过公式 \( T = (n-1) \times \sum S_i \) 计算。 +3. **动态规划分组**: + - 初始化二维数组 `dp_old`,`dp_old[i][j] = true` 表示第一组和为 \( i \)、第二组和为 \( j \) 是可行的。 + - 对于每个围栏长度,更新状态:将当前围栏放入第一组、第二组或第三组,并确保新的组和不超过 \( (T-1)/2 \)(即严格小于 \( T/2 \))。 + - 使用滚动数组优化空间,每次更新 `dp_new` 并赋值给 `dp_old`。 +4. **检查可行解并计算最大面积**: + - 遍历所有状态 `(i, j)`,如果 `dp_old[i][j] = true` 且第三组和 \( c = T - i - j < T/2 \),则三条边 \( (i, j, c) \) 可构成三角形。 + - 使用海伦公式计算面积:半周长 \( s = T/2 \),面积 \( A = \sqrt{s(s-i)(s-j)(s-c)} \)。 + - 记录最大面积,乘以 10000 后向下取整输出;若无解,输出 -1。 + +### 复杂度分析 +- **时间**:围栏总数 \( m = n(n-1)/2 \leq 45 \),动态规划状态数 \( O(m \times (T/2)^2) \),最坏情况 \( T \leq 1800 \),状态数约 3645 万,可接受。 +- **空间**:使用两个二维数组,大小 \( O((T/2)^2) \),约 810000 个布尔值。 + +### 代码实现 +```cpp +#include +#include +#include +#include +using namespace std; + +int main() { + int n; + cin >> n; + vector S(n); + for (int i = 0; i < n; i++) { + cin >> S[i]; + } + + vector lengths; + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + lengths.push_back(S[i] + S[j]); + } + } + int m = lengths.size(); + int T_total = 0; + for (int L : lengths) { + T_total += L; + } + + int a_max = (T_total - 1) / 2; + int b_max = a_max; + + vector> dp_old(a_max + 1, vector(b_max + 1, false)); + dp_old[0][0] = true; + + for (int k = 0; k < m; k++) { + int L = lengths[k]; + vector> dp_new(a_max + 1, vector(b_max + 1, false)); + for (int i = 0; i <= a_max; i++) { + for (int j = 0; j <= b_max; j++) { + if (dp_old[i][j]) { + if (i + L <= a_max) { + dp_new[i + L][j] = true; + } + if (j + L <= b_max) { + dp_new[i][j + L] = true; + } + dp_new[i][j] = true; + } + } + } + dp_old = dp_new; + } + + double max_area = -1.0; + for (int i = 0; i <= a_max; i++) { + for (int j = 0; j <= b_max; j++) { + if (dp_old[i][j]) { + int c = T_total - i - j; + if (c < T_total / 2.0) { + double s = T_total / 2.0; + double area = sqrt(s * (s - i) * (s - j) * (s - c)); + if (area > max_area) { + max_area = area; + } + } + } + } + } + + if (max_area < 0) { + cout << -1 << endl; + } else { + long long result = static_cast(max_area * 10000); + cout << result << endl; + } + + return 0; +} +``` + +### 代码说明 +1. **输入处理**:读取板材数量 \( n \) 和长度数组 \( S \)。 +2. **围栏生成**:计算所有不同板材对的围栏长度并存储。 +3. **动态规划初始化**:`dp_old[0][0] = true` 表示初始状态(无围栏时两组和均为0)。 +4. **状态转移**:对每个围栏,尝试放入三组之一,更新状态数组。 +5. **面积计算**:遍历所有可行状态,检查三角形条件,用海伦公式计算面积并记录最大值。 +6. **输出**:最大面积乘以 10000 后向下取整输出,若无解输出 -1。 \ No newline at end of file diff --git a/src/7/16/T633664f.cpp b/src/7/16/T633664f.cpp new file mode 100644 index 0000000..f454df8 --- /dev/null +++ b/src/7/16/T633664f.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include + +using ll = int64_t; + +ll n; +std::vector s; +std::vector edg; + +double getArea(double a,double b,double c){ + double s = a+b+c; + return std::sqrt(s*(s-a)*(s-b)*(s-c)); +} + +void dfs(ll depth){ + for(ll i=0;i>n; + s.reserve(n+1); + edg.reserve(n*(n-1)/2+1); + + for(ll i=0;i>tmp; + s.emplace_back(tmp); + } + + for(ll i=0;i