2021. 1. 24. 16:05ㆍ알고리즘/알고리즘 문제 [medium]
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
70
|
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
using namespace std;
int T, n;
int r[200];
int p[200];
vector<double> ratio;
int add[200];
void potion()
{
if(ratio.back() <= 1.0)
{
for(int i = 0; i < n; i++)
cout<<r[i] - p[i]<<" ";
cout<<"\n";
}
else
{
double maxr = ratio.back();
int ratioN = ratio.back();
for(int i = 0; i < n; i++)
if(ratioN * r[i] - p[i]> 0)
add[i] = ratioN * r[i] - p[i];
for(int i = 0; i < n; i++)
{
double pr = (double)(p[i]+add[i])/r[i];
while(ratio.back() > pr)
{
add[i]++;
pr = (double)(add[i]+p[i])/r[i];
}
if(maxr < pr) maxr = pr;
}
if(maxr > ratio.back())
{
for(int i = 0; i < n; i++)
if(((int)ceil(maxr) * r[i] - (p[i] + add[i])) > 0)
add[i] += ((int)ceil(maxr) * r[i] - (p[i] + add[i]));
}
for(int i = 0; i < n; i++)
cout<<add[i]<<" ";
cout<<"\n";
}
}
int main()
{
cin>>T;
for (int i = 0; i < T; i++)
{
ratio.clear();
memset(add, 0, sizeof add);
cin>>n;
for(int j = 0; j < n; j++)
cin>>r[j];
for(int j = 0; j < n; j++)
cin>>p[j];
ratio.resize(n);
for(int j = 0; j < n; j++)
ratio[j] = (double)p[j]/r[j];
sort(ratio.begin(), ratio.end());
potion();
}
}
|
cs |
1. 풀이
모든 재료의 비율을 똑같이 맞추는 문제이다.
따라서 만약 가장 큰 비율보다 작을 경우 비율을 맞추기 위해
하나씩 추가하여 비율을 맞추었다.
또한 위 코드에서는 한번 처리 후 비율이 맞지 않을경우
가장 큰 비율을 올림하여 레시피의 정수배만큼 제조하였다
2. 책의 풀이1
i번 재료가 put[i]/recipe[i] 배 들어갔으니
j번 재료도 최소한 그만큼 넣어야한다는 것을 식으로 풀었다.
put[j] >= recipe[j] * put[i] / recipe[i]
이식을 통해 냄비에 재료를 더 넣지 않아도 될 때까지
이중 포문으로 i와 j를 비교하였다.
3. 책의 풀이2
모든 재료중 가장 많이 들어간 재료를 찾는다.
X = max (put[i]/recipe[i])
모든 재료는 X배 이상 들어가야한다는 사실을 알 수 있다.
하지만 recipe[i]*X는 항상 정수여야한다.
따라서 실제 곱해야하는 유리수는 다음과 같다
X <= Y = a/b
이제 Y를 찾으면 된다.
모든 i에 대해 recipe[i]*Y 가 정수가 되기 위해서는
b가 recipe[]의 모든 수들의 약수가 되어야한다.
즉. b는 recipe들의 최대 공약수여야 한다.
Xb <= a 를 만족하는 최소의 정수 a를 선택하면 문제를 풀 수 있다.
모든 레시피는 이제 1/b병으로 나눌 수 있게되었다.
그러므로 x이상이 될때 까지 1/b병을 계속 추가 시키면 답을 구할 수 있다.
또한 최대값 x를 구하고 거기에 b를 곱해서 a를 얻는게 아니라
|b*put[i]/recipe[i]|의 최대치를 직접 구함으로써 분수연산을 없앨 수 있다.
( ceil == (a+b-1)/b)
'알고리즘 > 알고리즘 문제 [medium]' 카테고리의 다른 글
[문자열][시간 초과]HABIT 말장난 (0) | 2021.02.03 |
---|---|
[비트 마스크] GRADUATION 졸업 학기 문제 (0) | 2021.01.30 |
[결정 문제] CANADATRIP 캐나다 여행 (0) | 2021.01.21 |
[결정 문제][그래프] ARCTIC 북극 기지 (0) | 2021.01.21 |
[조합 탐색] ALLERGY 알러지가 심한 친구들 (0) | 2021.01.20 |