update
This commit is contained in:
parent
6573de0ce0
commit
714f9830be
2
src/7/16/Area0.in
Normal file
2
src/7/16/Area0.in
Normal file
@ -0,0 +1,2 @@
|
||||
4
|
||||
5 6 7 10
|
1
src/7/16/Area0.out
Normal file
1
src/7/16/Area0.out
Normal file
@ -0,0 +1 @@
|
||||
3394819
|
2
src/7/16/Area1.in
Normal file
2
src/7/16/Area1.in
Normal file
@ -0,0 +1,2 @@
|
||||
5
|
||||
18 4 17 5 1
|
1
src/7/16/Area1.out
Normal file
1
src/7/16/Area1.out
Normal file
@ -0,0 +1 @@
|
||||
15579794
|
2
src/7/16/Area2.in
Normal file
2
src/7/16/Area2.in
Normal file
@ -0,0 +1,2 @@
|
||||
10
|
||||
10 18 12 2 14 17 6 12 7 10
|
1
src/7/16/Area2.out
Normal file
1
src/7/16/Area2.out
Normal file
@ -0,0 +1 @@
|
||||
454559413
|
106
src/7/16/T633664.md
Normal file
106
src/7/16/T633664.md
Normal file
@ -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 <iostream>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
int n;
|
||||
cin >> n;
|
||||
vector<int> S(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
cin >> S[i];
|
||||
}
|
||||
|
||||
vector<int> 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<vector<bool>> dp_old(a_max + 1, vector<bool>(b_max + 1, false));
|
||||
dp_old[0][0] = true;
|
||||
|
||||
for (int k = 0; k < m; k++) {
|
||||
int L = lengths[k];
|
||||
vector<vector<bool>> dp_new(a_max + 1, vector<bool>(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<long long>(max_area * 10000);
|
||||
cout << result << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 代码说明
|
||||
1. **输入处理**:读取板材数量 \( n \) 和长度数组 \( S \)。
|
||||
2. **围栏生成**:计算所有不同板材对的围栏长度并存储。
|
||||
3. **动态规划初始化**:`dp_old[0][0] = true` 表示初始状态(无围栏时两组和均为0)。
|
||||
4. **状态转移**:对每个围栏,尝试放入三组之一,更新状态数组。
|
||||
5. **面积计算**:遍历所有可行状态,检查三角形条件,用海伦公式计算面积并记录最大值。
|
||||
6. **输出**:最大面积乘以 10000 后向下取整输出,若无解输出 -1。
|
49
src/7/16/T633664f.cpp
Normal file
49
src/7/16/T633664f.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using ll = int64_t;
|
||||
|
||||
ll n;
|
||||
std::vector<ll> s;
|
||||
std::vector<ll> 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<edg.size()-2+depth;i++){
|
||||
ll sum{};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
std::iostream::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
std::cout.tie(nullptr);
|
||||
|
||||
std::cin>>n;
|
||||
s.reserve(n+1);
|
||||
edg.reserve(n*(n-1)/2+1);
|
||||
|
||||
for(ll i=0;i<n;i++){
|
||||
ll tmp;
|
||||
std::cin>>tmp;
|
||||
s.emplace_back(tmp);
|
||||
}
|
||||
|
||||
for(ll i=0;i<s.size();i++){
|
||||
for(ll j=0;j<s.size();j++){
|
||||
if(i==j)continue;
|
||||
edg.emplace_back(i+j);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user