일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- DP
- 비트마스크
- DisjointSet
- 에라토스테네스의 체
- boj
- lis
- 이진탐색
- BFS
- 플로이드와샬
- MST
- 세그먼트트리
- 이분탐색
- 좌표압축
- 크루스칼
- 삼분탐색
- 펜윅트리
- dfs
- 투포인터
- 이분매칭
- 누적합
- 그리디
- lca
- 수학
- 위상정렬
- LazyPropagation
- 다익스트라
- 브루트포스
- 정렬
- 백준
- 구현
Archives
- Today
- Total
lastknight00
[백준] 커플 만들기(1727) 본문
문제 링크 : [백준] 커플 만들기(1727)
문제 설명
두 1차원 배열이 주어졌을 때, 원소의 갯수가 작은 배열의 모든 원소들을 원소의 갯수가 큰 배열과 1:1 쌍을 이룰 때, 쌍을 이룬 값들의 차이의 합이 최소가 되는 값을 구하여라.
입력
n(첫번째 배열의 원소 갯수, 1<=n<=1,000)
m(두번째 배열의 원소 갯수, 1<=m<=1,000)
Di(첫번째 배열의 원소들, 1<=Di<=1,000,000)
Ei(두번째 배열의 원소들, 1<=Ei<=1,000,000)
2 1
10 20
15
출력
5
카테고리
#DP, #정렬
시간 복잡도 상한
O(N2 * logn) 까지 가능합니다.
해결 방법
- 최대한 많은 쌍을 구해야하기 때문에, 원소의 갯수가 작은 배열(As을 기준으로 다른 배열로 모든 원소들의 쌍을 구해주면 됩니다.
- 두 배열을 오름차순으로 정렬 했을 때, A배열의 원소 Ai, Ai+k과 B배열의 원소 Bj, Bj+l이 있다고 할 때(k,l>0),
2-1. Ai+k=Ai+Va
2-2. Bj+l=Bj+Vb
2-3. Ai-Bj=T
2-3. 위 처럼 정의하고, Ai과 Bj+l, Ai+k과 Bj이 짝을 이룬다고 하면, 두 쌍의 차이의 합은
|Ai-Bj+l|+|Ai+k-Bj| = |Ai-Bj-Vb|+|Ai-Bj+Va|=|T-Vb|+|T+Va| -> (1)
2-4. Ai과 Bj, Ai+k과 Bj+l이 짝을 이룬다고 하면, 두 쌍의 차이의 합은
|Ai-Bj|+|Ai+k-Bj+l| = |Ai-Bj|+|Ai+Va-Bj-Vb|=|T|+|T+Va-Vb| -> (2)
2-5. (1)과 (2)의 대소비교를 위하여, 각 절대값들의 제곱을 구합니다.
1) (1) -> (T-Vb)2+(T+Va)2 = 2T2+2TVa-2TVb+Va2+Vb2
2) (2) -> T2+(T+Va-Vb)=2T2+2TVa-2TVb+Va2+Vb2-2VaVb
3) 양 변에서 공통 부분을 제거하고 식을 정리하면,
(1)-2VaVb=(2)이 됩니다.- 두 배열은 오름차순으로 정렬 되어 있기 때문에, Va, Vb는 항상 0보다 같거나 큽니다.
- 즉 (1)>=(2) 식이 항상 성립합니다.
- 2의 정리들을 활용하여, 오름차순으로 정렬 된 배열들을, 기준 배열에서 다른 배열로 짝을 이룰 때, 인덱스가 역순으로 이어지는 경우는 제외할 수 있습니다.
- 아직 경우의 수가 많지만, 기준 배열의 한 인덱스가 타겟의 한 인덱스를 선택하거나 하지 않는 경우, 두 경우에 대해 sub problem으로 문제가 제정의 될 수 있으므로, DP를 활용하여 문제에 접근 할 수 있습니다.
시간복잡도
O(nlogn)+O(mlonm)+O(n*m)
코드
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long l;
int n,m,d[1000],e[1000],i,j,v[1000][1000];
l f[1000][1000];
l a(l x){return x>0?x:-x;}
l b(l a,l c){return a>c?c:a;}
l r(int* a1,int* a2,int x,int y){
if(!x)return 0;
if(!y)return 1000000000000;
x--;y--;
if(v[x][y])return f[x][y];
f[x][y]=a(a1[x]-a2[y])+r(a1,a2,x,y);
f[x][y]=b(f[x][y],r(a1,a2,x+1,y));
v[x][y]=1;
return f[x][y];
}
int main(){
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)scanf("%d",d+i);
for(i=0;i<m;i++)scanf("%d",e+i);
sort(d,d+n);sort(e,e+m);
printf("%lld",n<m?r(d,e,n,m):r(e,d,m,n));
}
'PS' 카테고리의 다른 글
[백준] 증가 수열의 갯수(17409) (3) | 2020.05.26 |
---|---|
[백준] 인경호의 징검다리(11583) (0) | 2020.05.26 |
[백준] 로봇 프로젝트(3649) (0) | 2020.05.26 |
[백준] 개똥벌레(3020) (0) | 2020.05.26 |
[백준] 택배(1719) (0) | 2020.05.26 |
Comments