시간 제한메모리 제한제출정답맞은 사람정답 비율
2 초128 MB129934023227.008%

문제

여자친구가 없는 남자 n명과 남자친구가 없는 여자 m명을 불러 모아서 이성 친구를 만들어 주기로 하였다. 하지만 아무렇게나 해줄 수는 없고, 최대한 비슷한 성격의 사람들을 짝 지어 주기로 하였다.

당신은 뭔가 알 수 없는 방법으로 각 사람의 성격을 수치화 하는데 성공하였다. 따라서 각 사람의 성격은 어떤 정수로 표현된다. 이와 같은 성격의 수치가 주어졌을 때, 우선 최대한 많은 커플을 만들고, 각 커플을 이루는 두 사람의 성격의 차이의 합이 최소가 되도록 하려 한다. 남자-여자 커플만 허용된다.

입력

첫째 줄에 n, m(1≤n, m≤1,000)이 주어진다. 다음 줄에는 n명의 남자들의 성격이 주어진다. 그 다음 줄에는 m명의 여자들의 성격이 주어진다. 성격은 1,000,000이하의 자연수이다.

출력

첫째 줄에 성격의 차이의 합의 최솟값을 출력한다.

예제 입력 

2 1
10 20
15

예제 출력 

5

힌트



















풀다가 머리에 쥐나서.. 섬광탄 맞은 것처럼 띵~~~하게 하는 난이도네요..(라헬이..생각나고..)

처음에 dp인줄도 모르고 그리디로 풀어서 엄청 틀렸네요..



이 문제를 풀 때 꿀팁은 항상 여자 혹은 남자의 데이터 수가 많다고 생각하고 푸는 것입니다.

저는 무조건 여자가 많게 만들어서 풀었습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
    scanf("%d %d"&m, &g);
 
    for(int i = 0; i < m; i++scanf("%d", data1 + i);
    for(int j = 0; j < g; j++scanf("%d", data2 + j);
 
    if(m > g)
    {
        swap(data1, data2);
        swap(m, g);
    }
 
    sort(data1, data1 + m);
    sort(data2, data2 + g);
cs


인풋과 정렬까지 하는 부분입니다.

만약 m(남자)가 크면 g(여자)와 swap을 해서 데이터를 바꿔줍니다.


남자의 데이터(1, 2, 3, 4), 여자의 데이터(a,b,c,d,e,f,g)라고 가정하겠습니다.


1

2

3

4


1가 선택할 수 있는 여자는 a,b,c,d입니다.


a

b

c

d

e

f

g


2가 선택할 수 있는 여자는 b,c,d,e입니다.

a

b

c

d

e

f

g


3이 선택할 수 있는 여자는 c,d,e,f입니다.


a

b

c

d

e

f

g


4가 선택할 수 있는 여자는 d,e,f,g입니다.


a

b

c

d

e

f

g



dp는 2차원으로 정의합니다.


dp[남자][여자] = 남자가 여자를 선택했을 때 까지 궁합의 합의 최솟값입니다.


예를 들어 1번 남자가 b번 여자를 선택한다면 2번 남자는 c,d,e만 선택할 수 있습니다.


dp[1][a]는 (1번 남자 성격) - (a번 여자 성격)의 절대값입니다.


그리고 dp[1][b]는 (1번 남자 성격) - (b번 여자 성격)의 절대값과 dp[1][a] 둘 중에 작은 값을 선택해서 저장합니다.

이 작업을 dp[1][d]까지 반복합니다.


점화식으로 표현하면 이 부분은 i == 0일 때 입니다.

1
2
3
4
5
6
7
8
    for(int i = 0; i < m; i++)
    {
        if(i == 0)
        {
            dp[0][0= abs(data1[0- data2[0]);
 
            for(int j = 1; j < g - (m - i - 1); j++) dp[i][j] = min(dp[i][j - 1], abs(data1[0- data2[j]));
        }
cs


이후에 2-b를 연결한다고 생각하면 2-b의 절대값에 1-a를 더합니다. 그리고 dp[2][b]에 그 값을 저장합니다.


2-c를 연결한다고 생각하면 2-c의 절대값을 구하여서 dp[1][b]까지의 최솟값에 더하고 dp[2][b]값과 비교하여 작은 값을 저장합니다.

이 부분이 핵심이며.. 이 작업을 반복하면 정답을 구할 수 있습니다.


1
2
3
4
5
6
7
8
        else
        {
            for(int j = i; j < g - (m - i - 1); j++)
            {
                if(j == i) dp[i][j] = dp[i - 1][j - 1+ abs(data1[i] - data2[j]);
                else dp[i][j] = min(dp[i - 1][j - 1+ abs(data1[i] - data2[j]), dp[i][j - 1]);
            }
        }
cs



아래는 풀 코드입니다.


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <cstdio>
#include <stack>
 
#define ull unsigned long long
#define ll long long
#define mp make_pair
#define MAX_SIZE 1010
#define MAX_MOVE 31
 
using namespace std;
 
typedef pair<intint> p;
 
int data1[MAX_SIZE];
int data2[MAX_SIZE];
int dp[MAX_SIZE][MAX_SIZE];
int m, g;
 
int abs(int a)
{
    if(a>=0return a;
    else return -a;
}
 
int main()
{
    scanf("%d %d"&m, &g);
 
    for(int i = 0; i < m; i++scanf("%d", data1 + i);
    for(int j = 0; j < g; j++scanf("%d", data2 + j);
 
    if(m > g)
    {
        swap(data1, data2);
        swap(m, g);
    }
 
    sort(data1, data1 + m);
    sort(data2, data2 + g);
 
    for(int i = 0; i < m; i++)
    {
        if(i == 0)
        {
            dp[0][0= abs(data1[0- data2[0]);
 
            for(int j = 1; j < g - (m - i - 1); j++) dp[i][j] = min(dp[i][j - 1], abs(data1[0- data2[j]));
        }
        else
        {
            for(int j = i; j < g - (m - i - 1); j++)
            {
                if(j == i) dp[i][j] = dp[i - 1][j - 1+ abs(data1[i] - data2[j]);
                else dp[i][j] = min(dp[i - 1][j - 1+ abs(data1[i] - data2[j]), dp[i][j - 1]);
            }
        }
    }
 
    printf("%d\n", dp[m - 1][g - 1]);
 
    return 0;
 
cs


'알고리즘 > 다이나믹 프로그래밍(DP)' 카테고리의 다른 글

[2133] 타일 채우기  (0) 2017.04.20
[1309] 동물원  (0) 2017.04.20
[2294] 동전 2  (0) 2017.04.19
[2293] 동전 1  (4) 2017.04.19
[2240] 자두나무  (0) 2017.04.05

+ Recent posts