본문 바로가기

성우리뷰

매출하락 최소화

출처: https://yabmoons.tistory.com/625 [얍문's Coding World..]

3차for문 지랄지랄 하다가 걍 구글에 검색해서 이분 거 봤다. 개어렵다...

 

다시 직접 코드 쓰면서 이해할라고 적음.

 

DP를 구성 --> 각 인원이, 참가한다? 안 한다? 의 [300000][2]로 배열 만든다.

Min 함수는 더 작은 값 내보내는 함수.

Make_Relation 통해, Node[parent] 벡터에, 그 자식을 넣는다. (팀장이 되는 애의 vector에 팀원 번호 넣기)

 

Cur은, 현재 팀장이 되는 노드다. 해당 Cur : 팀장의 vector size만큼, DFS를 돌린다.

 

이 때, Leaf Node가 참인, 즉 팀원이 없는 애라면, 다시 말해 마지막 노드까지 도달했다면, 

DP[CUR]에서의 최소값은 걔가 참가하거나, 안 하거나다.

따라서

DP[cur][0] == cur이 참가 안한다 == 0

DP[cur][1] == Cost[cur - 1]

return;

 

이렇게 한 팀장의 모든 팀원을 돌았을 땐, 팀장은 3개의 케이스 중 하나를 골라야 한다. 

1) 자기가 참가해야 하는 경우. 이 경우, 팀원이 나가든 말든 일단 신경쓰지 않는다.

2 -1 ) 자기가 참가하지 않고, 팀원을 내보내야 하는 경우 중, 이미 팀원이 나가는 게 이득인 경우

2 -2 ) 자기가 참가하지 않고, 팀원을 내보내야 하는 경우 중, 팀원이 무조건 나가야 하는 경우

 

즉, 만약 CUR이 팀원이자 팀장인 위치일 때, 자기 child 중 팀장인 애가 당첨되었다면? 이건 2-1에 해당한다.

근데, 자기 child 중 팀장인 애가 당첨되지 않은 상황에, 팀장 역시 cost가 크다면? 무조건 child 중 하나를 선택해 내보내야 한다. 이는 2-2에 해당한다.

 

1)은 다음과 같다.

int sum = 0;
for(int i=0; i<Node[cur].size(); i++) {
	int child = Node[cur][i];
	sum += Min(DP[child][0], DP[child][1]);
}
DP[cur][1] = sum + cost[cur-1];

2-1)은 다음과 같다.

int sum = 0;
bool childattend =false;

for(int i=0; i<Node[cur].size(); i++) {
	int child = Node[cur][i];
	sum += Min(DP[child][0], DP[child][1]);
    
    if(DP[child][0] > DP[child][1]) // 만약 해당 child가 나가는게, 나가지 않는 것보다 낫다면
    	childattend = true;			// cur은 굳이 나가지 않아도 된다.
}

DP[cur][1] = sum + cost[cur-1];

if(childattend = true) 
	DP[cur][0] = sum;

2-2)는

int sum = 0;
bool childattend = false;

//아무도 child중 지원자가 없다면, 아무나 cost가 참가 하는 거랑 참가 안하는 거의 차이가 
//제일 작은 child를 끌고 데려와야 한다.
int Min = 210000000;

for(int i=0; i<Node[cur].size(); i++) {
	int child = Node[cur][i];
	sum += Min(DP[child][0], DP[child][1]);
    
    if(DP[child][0] > DP[child][1]) // 만약 해당 child가 나가는게, 나가지 않는 것보다 낫다면
    	childattend = true;			// cur은 굳이 나가지 않아도 된다.
    else
    	Min = Min < (DP[cur][1] - DP[cur][0]) ? Min : (DP[cur][1] - DP[cur][0]);
        //그게 아니라면, 참가하는 것 - 참가 안하는 것이 제일 차가 작은 애를
        //억지로 끌고 데리고 나와야됨
}

DP[cur][1] = sum + cost[cur-1];

if(curattend = true) 
	DP[cur][0] = sum;
else
	DP[cur][0] = sum + Min;  //이 경우, 억지로 끌려나온 애(Min) + 그간 더해둔 것(sum)

최종 답은, 사장인 [1]이 [1][0](참가 안하기) 또는 [1][1](참가하기)

#include <string>
#include <vector>
 
#define MAX 300010
using namespace std;
 
int DP[MAX][2];
vector<int> Node[MAX];
vector<int> Cost;
 
int Min(int A, int B) { return A < B ? A : B; }
 
void Make_Relation(vector<int> sales, vector<vector<int>> links)
{
    for (int i = 0; i < links.size(); i++)
    {
        int Parent = links[i][0];
        int Child = links[i][1];
        Node[Parent].push_back(Child);
    }
}
 
void DFS(int Cur)
{
    bool leafNode = true;
    
    for(int i=0; i<Node[cur].size(); i++) {
    	int next = Node[cur][i];
        leafNode = false;   
        DFS(next);
    }
    
    if(leafNode) {
        Dp[cur][0] = 0;
        Dp[cur][1] = Cost[cur-1];
        return;
    }
    
    else {
    	int sum = 0;
        int min = 2100000000;
        bool childattend = false;
        
        for(int i=0; i<Node[cur].size(); i++) {
        	int child = Node[cur][i];
            sum += Min(DP[child][0], DP[child][1]);
            
            if(DP[child][0] > DP[child][1]) childattend = true;
            min = min < (DP[child][1] - DP[child][0]) ? 
            	min : (DP[child][1] - DP[child][0]);
        }
        
        DP[cur][1] = sum + Cost[cur];
        if(childattend) DP[cur][1] = sum;
        else DP[cur][1] = sum + min;
    }
}
 
int solution(vector<int> sales, vector<vector<int>> links) 
{
    int answer = 0;
    Cost = sales;
    Make_Relation(sales, links);
    DFS(1);
    answer = Min(DP[1][0], DP[1][1]);
    return answer;
}

 

 

아래는 하다 포기한거

#include <string>
#include <vector>
#include <algorithm>

using namespace std;
vector<pair<int, int>> v;
vector<int> s;

int answer = 0;
int dfs(int head, int min, int headnum) {
    int param;
    //a: head와 맞는 녀석이 있는가?
    //b: 그중 부모노드도 되는 게 있는가?
    //c: 된다면, 자식노드와 비교해서 가장 적은 cost는?
    
    for(int a=0; a<v.size(); a++) {
        //부모노드가 head가 아닌 pair은 pass
        if(head != v[a].first) {
            continue;
        }
        
        for(int b=0; b<v.size(); b++) {
            if(v[a].second == v[b].first) {
                
                //최소값 찾기
                for(int c=0; c<v.size(); c++) {
                    if(v[c].first == v[b].second) {
                        param = s[v[b].first - 1] < s[v[c].first - 1] ? 
                            s[v[b].first - 1] : s[v[c].first - 1];
                    }
                }
                
                answer += dfs(v[a].second, param, s[v[a].second - 1]);
                break;
            }
        }
    }
    int minimum;
    for(int a=0; a<v.size(); a++) {
        if(v[a].first == head)
            minimum = headnum < min + s[v[a].second - 1] ?
            headnum : s[v[a].second - 1];
        else
            continue;
    }
    if(headnum == minimum) {
        return 0;
    }
    else {
        return minimum;
    }
    
}

int solution(vector<int> sales, vector<vector<int>> links) {
    copy(sales.begin(), sales.end(), s.begin() );
    for(int a=0; a<links.size(); a++) {
        v.push_back(make_pair(links[a][0], links[a][1]));
    }
    sort(v.begin(), v.end());
    
    int min = sales[0];
    int headnum;
    for(int a=0; a<links.size(); a++) {
        if(v[a].first == 1) {
            min = min < sales[v[a].second - 1] ? min : sales[v[a].second - 1];
            headnum = sales[0];
        }
        else
            break;
    }
    
    answer += dfs(1, min, headnum);
    return answer;
}

 

 

 

'성우리뷰' 카테고리의 다른 글

입국심사 (with java)  (0) 2021.07.12
징검다리건너기  (2) 2021.05.27
임시 공부용  (1) 2021.05.24
sw 문제 모의 역량테스트) 보물상자 비밀번호  (0) 2021.05.13
2021 카카오)순위 검색  (1) 2021.05.05