Algorithm/Algorithm 문제 풀이
[BAE/<JOON> 문제풀이] 1139. 울타리
폭풍저그머성찡
2023. 11. 19. 16:14
https://www.acmicpc.net/problem/1139
1139번: 울타리
$A \le B \le C$를 만족하는 $A$, $B$, $C$는 $A+B>C$를 만족할 때만 울타리를 만들 수 있다. 그리고, 그 때 넓이는 $\sqrt{p(p-A)(p-B)(p-C)}$이다. 여기서 $p=(A+B+C)/2$ 이다.
www.acmicpc.net
서론
N 이 10 초반 ~ 10 후반 인 문제는 대부분 비트마스크 문제였던 것 같다.
풀이
각각의 울타리 사용 여부를 비트에 대응시키고 아직 확인하지 않은 상태일 때만 검사를 진행하면 된다.
한번에 3개씩 묶어서 조작해야하니까 구현이 살짝 복잡하긴 하다.
코드
더보기
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct pa {
ll sum, cnt;
};
struct pos {
int x, y, cnt;
};
int mvx[4] = { 0 ,1, 0, -1 };
int mvy[4] = { 1, 0, -1, 0 };
vector<short> arr; int n; vector<double> dp; double mx = 0;
double gets(double a, double b, double c) {
vector<double> sl = { a, b, c };
sort(sl.begin(), sl.end());
if (sl[0] + sl[1] <= sl[2]) return -1;
double p = (sl[0] + sl[1] + sl[2]) / 2;
return sqrt(p * (p - sl[0]) * (p - sl[1]) * (p - sl[2]));
}
double getmx(int bm) {
double& ret = dp[bm];
if (ret > 0) return ret;
vector<int> avlist;
for (int i = 0; i < n; i++) {
if ((bm & (1 << i)) == 0) {
avlist.push_back(i);
}
}
if (avlist.size() < 3) return ret = 0;
int m = avlist.size();
for (int i = 0; i < m - 2; i++) {
for (int j = i + 1; j < m - 1; j++) {
for (int k = j + 1; k < m; k++) {
int nbm = bm | (1 << avlist[i]) | (1 << avlist[j]) | (1 << avlist[k]);
double s = gets(arr[avlist[i] + 1], arr[avlist[j] + 1], arr[avlist[k] + 1]);
if (s == -1) continue;
double p = s + getmx(nbm);
ret = p > ret ? p : ret;
}
}
}
return ret;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0);
cin >> n; arr = vector<short>(n + 1); dp = vector<double>((1 << n) - 1, 0);
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
printf("%.9lf", getmx(0));
return 0;
}