최근 풀었던 문제 중 다양한 알고리즘이 가능한 문제라 인상적
생각해볼 수 있는 모든 알고리즘을 고려한 후 시간 복잡도를 분석해보도록 한다.
vector<int> picks, vector<string> minerals
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int solution(vector<int> picks, vector<string> minerals)
{
int answer = 0;
int dia, iron, stone;
dia = picks[0];
iron = picks[1];
stone= picks[2];
// 캐고자 하는 광물의 인덱스
int idx = 0;
// 다이아 > 철 > 돌 순으로 사용
while (dia-- && idx < minerals.size())
{
for (int i = 0;i < 5;i++)
{
if (idx >= minerals.size())
break;
answer++;
idx++;
}
}
while (iron-- && idx < minerals.size())
{
for (int i = 0;i < 5;i++)
{
if (idx >= minerals.size())
break;
string mineral = minerals[idx];
if (mineral == "diamond")
{
answer += 5;
}
else
answer++;
idx++;
}
}
while (stone-- && idx < minerals.size())
{
for (int i = 0;i < 5;i++)
{
if (idx >= minerals.size())
break;
string mineral = minerals[idx];
if (mineral == "diamond")
answer += 25;
else if (mineral == "iron")
answer += 5;
else
answer++;
idx++;
}
}
cout << answer << endl;
return answer;
}
c.f.
solution({ 1,1,0 },{ "stone", "stone", "iron", "stone", "diamond", "diamond", "diamond", "diamond", "diamond", "diamond" });
반례가 발생하는 이유는 피로도가 많이 드는 광물이 뒤에 위치한 경우 뒤에 남은 곡괭이(덜 좋은 곡괭이)를 사용하게 되므로
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <stack>
using namespace std;
// 광물 별 피로도 순위를 매기기 위한 함수
int getVal(string mineral)
{
if (mineral == "diamond")
return 3;
else if (mineral == "iron")
return 2;
else
return 1;
}
// 곡괭이별 광물캐는 비용(피로도)
int countVal(string pick, string mineral)
{
if (pick == "dia")
return 1;
else if (pick == "iron")
{
if (mineral == "diamond")
return 5;
else
return 1;
}
else
{
if (mineral == "dia")
return 35;
else if (mineral == "iron")
return 5;
else
return 1;
}
}
int solution(vector<int> picks, vector<string> minerals)
{
int answer = 0;
int dia = picks[0];
int iron = picks[1];
int stone = picks[2];
stack<string> tool;
// tot : 총 곡괭이의 수, tot_mineral : 총 캘 수 있는 광물의 수
int tot = dia + iron + stone;
for (int i = 0;i < stone;i++)
tool.push("stone");
for (int i = 0;i < iron;i++)
tool.push("iron");
for (int i = 0;i < dia;i++)
tool.push("dia");
// 캘수 있는거
int tot_mineral = tot * 5;
// 캘 거
int tot_minerals = minerals.size();
int real = min(tot_mineral, tot_minerals);
vector <pair<int,int>> sum_of_val;
for (int i = 0;i < real;i+=5)
{
int sum = 0;
int j;
for (j = 0;j < 5;j++)
{
if (i+j >= real)
break;
sum += getVal(minerals[i + j]);
}
sum_of_val.push_back({sum,i });
}
sort(sum_of_val.begin(), sum_of_val.end(),greater<>());
for (int i = 0;i < sum_of_val.size();i++)
{
int idx = sum_of_val[i].second;
string pick = tool.top();
tool.pop();
if (idx + 5 < minerals.size())
{
for (int j = idx;j < idx + 5;j++)
{
answer += countVal(pick, minerals[j]);
}
}
else
{
for (int j = idx;j < minerals.size();j++)
answer += countVal(pick, minerals[j]);
}
}
cout << answer << endl;
return answer;
}
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <stack>
using namespace std;
int getVal(string mineral)
{
if (mineral == "diamond")
return 25;
else if (mineral == "iron")
return 5;
else
return 1;
}
int countVal(string pick, string mineral)
{
if (pick == "dia")
return 1;
else if (pick == "iron")
{
if (mineral == "diamond")
return 5;
else
return 1;
}
else
{
if (mineral == "diamond")
return 25;
else if (mineral == "iron")
return 5;
else
return 1;
}
}
int solution(vector<int> picks, vector<string> minerals)
{
int answer = 0;
int dia = picks[0];
int iron = picks[1];
int stone = picks[2];
stack<string> tool;
vector<string>minerals2;
// tot : 총 곡괭이의 수, tot_mineral : 총 캘 수 있는 광물의 수
int tot = dia + iron + stone;
for (int i = 0;i < stone;i++)
tool.push("stone");
for (int i = 0;i < iron;i++)
tool.push("iron");
for (int i = 0;i < dia;i++)
tool.push("dia");
// 캘수 있는거
int tot_mineral = tot * 5;
// 캘 거
int tot_minerals = minerals.size();
int real = min(tot_mineral, tot_minerals);
if (tot_minerals > tot_mineral)
{
for (int i = 0;i < tot_minerals;i++)
{
minerals2.push_back(minerals[i]);
}
minerals = minerals2;
}
vector <pair<int,int>> sum_of_val;
bool isFit = true;
for (int i = 0;i < real;i+=5)
{
int sum = 0;
int j;
for (j = 0;j < 5;j++)
{
if (i+j >= real)
break;
sum += getVal(minerals[i + j]);
}
sum_of_val.push_back({sum,i });
}
sort(sum_of_val.begin(), sum_of_val.end(),greater<>());
for (int i = 0;i < sum_of_val.size();i++)
{
int idx = sum_of_val[i].second;
string pick = tool.top();
tool.pop();
if (idx + 5 < minerals.size())
{
for (int j = idx;j < idx + 5;j++)
{
answer += countVal(pick, minerals[j]);
}
}
else
{
for (int j = idx;j < minerals.size();j++)
answer += countVal(pick, minerals[j]);
}
}
cout << answer << endl;
return answer;
}
(이 정도 난이도에 LOC가 100에 가깝다는 것은 상당히 비효율적인 요소가 만다는 것이므로, 계속해서 개선 할 예정 )
풀이 완료 후 서치를 해보니 다양한 솔루션을 사용할 수 있었다.
역시 Problem solving보다 어려운 것은 error locate와 반례 찾기 이다. 코드가 길어질수록 얼마나 내 코드를 짜임새 있게 이해하고 있는가가 중요하다.
[출처]
https://school.programmers.co.kr/learn/courses/30/lessons/172927