백준: Gold4 - 1484, 1504
</br>
계속 계속
</br>
1484: 다이어트
https://www.acmicpc.net/problem/1484
a*2 - b*2 = G
일 때 a 구하기
for(int i = 1; i*i < g; i++){
if( g % i == 0 ) d.push_back(i);
}
for(int i = 0; i < d.size(); i++){
if( (g/d[i] + d[i] )% 2 == 1 ) continue;
int a = (g/d[i] + d[i]) / 2;
// int b = (g/d[i] - d[i]) / 2;
v.push_back(a);
}
sort(v.begin(), v.end());
if( v.size() ){
for(int a : v){
cout << a << '\n';
}
}
else cout << -1 << '\n';
i를 1부터 증가시키면서 이중 포문으로 다 검사해 보면 시간초과 날 거다.
그래서 생각한 게, a*2 - b*2 = (a+b)(a-b) = G
이므로, G의 약수들만 확인해 보면 되겠더라.
(a-b) * (a+b) = Di * Dn-i = G
이므로, 약수들 중 루트 G보다 작은 것들만 저장한다(a-b).
a-b = d
a+b = g/d
2a = g/d + d
로 식을 세울 수 있다. 훨씬 빠르다.
주의할 점은, 몸무게가 0이 될 수 없다는 거다. 약수(a-b)들을 구할 때 for문 종료 조건을 i*i < g
로 하면 된다.
ex) G = 9
(a, b)
(9, 0) <- 불가능
(25, 16) <- 답
</br>
1504: 특정한 최단 경로
https://www.acmcpc.net/problem/1504
1부터 n까지, v1과 v2를 꼭 거쳐서 가는 최단 경로
방법 1.
void dijkstra(int start){
for(int i = 1; i <= n; i++){
dist[i] = INT_MAX;
}
priority_queue<P, vector<P>, greater<P>> pq;
dist[start] = 0;
pq.push(mp(0, start));
while( pq.size() ){
int v = pq.top().second;
int w = pq.top().first;
pq.pop();
if( dist[v] < w ) continue;
for(int i = 0; i < graph[v].size(); i++){
int u = graph[v][i].second;
if( dist[u] > w + graph[v][i].first ){
dist[u] = w + graph[v][i].first;
pq.push(mp(dist[u], u));
}
}
}
}
// in main()
dijkstra(v1);
v11 = dist[1];
v1n = dist[n];
v1v2 = dist[v2];
dijkstra(v2);
v2n = dist[n];
v21 = dist[1];
if( v1v2 == INT_MAX ) cout << -1 << endl;
else if( v11 == INT_MAX || v2n == INT_MAX )
if( v1n != INT_MAX && v21 != INT_MAX )
cout << v1n + v21 + v1v2 << endl;
else cout << -1 << endl;
else if( v1n == INT_MAX || v21 == INT_MAX )
cout << v11 + v2n + v1v2 << endl;
else cout << min(v11 + v2n, v1n + v21) + v1v2 << endl;
다익스트라는 내나 그 다익스트라
경로를 생각해 보면,
1 - v1 - v2 - n // 1
(1 == v1) - v2 - n // 2
1 - v1 - (v2 == n) // 3
1 - v2 - v1 - n // 4
이 가능한데, 다익스트라에서 어차피 같은 노드 끼리의 거리는 0이므로 2, 3은 굳이 따로 고려해 줄 필요는 없었다.
따라서 v1-1, v2-v1, v2-n의 합과 v1-n, v2-v1, v2-1의 합 중 작은 걸 출력하면 된다.
만약 연결 되지 않을 경우도 있으므로 잘 고려해 주자
</br>
방법 2.
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]);
이 문제는 n이 800까지라서 O(V^3)인 플로이드 워셜로도 잘 풀린다.
</br>
굿
</br>
댓글남기기