3661 생일선물 https://www.acmicpc.net/problem/3661
1. 캔디캔디
사탕 $M$개로 친구들에게 나누어줬을 때 친구들이 원하는 사탕을 받지 못한 수의 제곱만큼 분노가 찬다.
이 분노들의 합을 최소화 시키는 문제이다.
굉장히 어렵게 느껴졌었다.
친구$i$가 얻고 싶은 사탕을 $candy_{i}$라 하면 $min \sum_{i=1}^{N} (candy_{i} - give_{i})^2$, $\sum_{i=1}^{N} give_{i} = M$이다.
줄 수 있는 사탕과 친구들이 얻고싶은 사탕은 정해져있으므로 못주는 사탕 또한 정해져있다.
못주는 사탕을 잘 분배해서 최솟값을 만들면 된다.
코드를 먼저 보겠다.
#include <cstdio>
#include <algorithm>
using namespace std;
int M, N;
int candy[100001];
int main() {
scanf("%d%d", &M, &N);
long long sum = -M;
for (int n = 0;n < N;n++) scanf("%d", &candy[n]), sum += (long long)candy[n];
sort(candy, candy + N);
long long ans = 0;
for (int n = 0;n < N;n++) {
long long w = min((long long)candy[n], sum / (N - n));
ans += w*w;
sum -= w;
}
printf("%lld\n", ans);
return 0;
}
| cs |
현재 sum에는 못주는 사탕의 개수가 들어있다.
잘 분배한다는 방법은 사탕을 많이 얻고싶어하는 사람에게 더 많이 주면 된다.
그 방법을 위와같이 정렬한후에 남은 사람 수로 나누어 그 값을 계산한다.
선물 가격이 P이고 N명의 사람들이 낼 수 있는 최대금액들이 정해져있다.
각 사람이 내는 금액과 P/N의 최댓값을 최소화 시키도록 하는 문제다.
위 문제처럼 정렬한 후에 적당하게 나눠주면 풀 수있다.
최댓값이 동일하면 돈을 많이 낼 수 있는사람이 더 내고
이마저도 동일하면 리스트 앞에 있는사람이 돈을 더 낸다는 조건이 있다.
코드를 먼저 보겠다.
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
int N, P;
int ans[101];
pair<int, int> g[101];
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &P, &N);
for (int n = 0;n < N;n++) {
scanf("%d", &g[n].second), g[n].first = n;
}
sort(g, g + N, [](pair<int, int> &a, pair<int, int> &b)->bool {
return a.second == b.second ? a.first > b.first : b.second > a.second;
});
for (int n = 0;n < N;n++) {
ans[g[n].first] = min(g[n].second, P / (N - n));
P -= ans[g[n].first];
}
if (P != 0) printf("IMPOSSIBLE\n");
else {
for (int n = 0;n < N;n++) printf("%d ", ans[n]);
printf("\n");
}
}
return 0;
}
| cs |
지속적으로 P값을 빼주면서 남은사람수로 나누어준다.
인덱스를 내림차순으로 정렬하는 이유는 동일한 금액에 대해서 뒤쪽에 있는 값이 더 작다.
(즉, 앞의 리스트사람이 많이 줄어듬 = 많이 냄)
많이 푸시면 익숙해 지실 듯 싶네요.
답글삭제이분이 어렵게 나오면 극혐스러울 정도로 어렵게 나오더라고요.
그래프 이론이랑 섞이거나.. 기하랑 섞이거나 하면.. 끔찍합니다.
캔디캔디는 '숨겨진 이분' 치고는 그나마 나은 편이긴 합니다..
캔디가 더 많이 필요한 사람에게 1개씩 주면 분노가 많이 줄어든다는 걸 이용해서요..
1637번 날카로운 눈 역시 이분탐색이고.. f(x) 자체는 이 친구보다 간단하긴 하지만..
난도는 더 어렵더라고요..
PS처음할때는 greedy랑 이분탐색이 매우 쉬운분야인줄 알았는데
삭제가면갈수록 생각을 더 이끌어내야되고 어려운 쪽이 많네요 ㅠㅠ
많이 푸는수밖에 없군요
네.. 많이 푸시는 수밖에 없어요.. ㅠㅠ
삭제사실 3197이.. 유니온 파인드 비슷하게 구현하는 게 정해일 거 같긴 한데요.
익숙해 지신다면 이분으로 구현해볼까? 라는 생각도 조금은 할 수 있지요.
이분 중에서 이런 유형도 꽤 나오긴 했습니다.
처음에 이분 우습게 봤다가 coci #6번 (아마 2990번일 겁니다) 보고..
만만한게 절대 아니구나.. 했습니다.
그나저나 설대 div1. 생각 외로 어렵더라고요.
슬라임(H) + 셔틀버스 + 관악산 + 정육면체 빼고는.. 구현을 못하겠네요..
와ㄷㄷ 전 관악산빼고는 손도 못댔는데 ㅋㅋ...
삭제좋은 조언 감사합니다. 더 열심히 해야겠네요 ㅎㅎ
그런데. dp는 진짜 어렵더라고요..
삭제그거 역시 제가 많이 안 풀어봐서 그런 것일수도 있긴 합니다..
충남대의 우유도시도 O(n^2)짜리 고민하느라 한참 걸리고..
5 ~ 9번 가량 틀린 거 같네요. 이상하게 어렵더라고요.. 빗물에서 말리고..
플로우 같은 다른 알고리즘도 해야 하는데.. 계속 몇 가지만 파다 보니..
그냥 대회에 나오는 것도 안하긴 했습니다.
(이래서 종만북이 좋은가 봅니다.)
dp도 어려워요 ㅠㅠ
삭제우유도시 우유축제 풀고 복붙하면서 잘못코딩해서 좀 틀렸었던 기억이 ㅋㅋ;;