[클래식 DP] Employment Planning

3875 단어
Description
A project manager wants to determine the number of the workers needed in every month. He does know the minimal number of the workers needed in each month. When he hires or fires a worker, there will be some extra cost. Once a worker is hired, he will get the salary even if he is not working. The manager knows the costs of hiring a worker, firing a worker, and the salary of a worker. Then the manager will confront such a problem: how many workers he will hire or fire each month in order to keep the lowest total cost of the project. 
 
Input
The input may contain several data sets. Each data set contains three lines. First line contains the months of the project planed to use which is no more than 12. The second line contains the cost of hiring a worker, the amount of the salary, the cost of firing a worker. The third line contains several numbers, which represent the minimal number of the workers needed each month. The input is terminated by line containing a single '0'. 
 
Output
The output contains one line. The minimal total cost of the project. 
 
Sample Input

     
     
     
     
3 4 5 6 10 9 11 0

 
Sample Output

     
     
     
     
199

대략적인 제목의 뜻:
제1행위 N은 분기를 대표한다(분기마다 하나의 상태).
두 번째 줄에는 세 가지 숫자가 있는데 그것이 바로hir(채용비),sal(월급),fir(해고비)이다.
세 번째 줄에는 N개의 숫자가 있는데 매 분기에 몇 명이 필요한지 나타낸다.
상태 방정식을 찾는 방법:
본 문제에 대해 상태는 현재(이 분기)와 이전 상태(지난 분기)를 대상으로 한다.또한 지난 시즌의 인원수에 따라 이번 분기의 채용 여부와 해고 여부에 영향을 미친다.
따라서num[13]: 12개월(최대)을 대표하고 매 분기 몇 명이 필요합니까?
dp[i][j]: i분기 수요를 대표하여 j개인을 보류한다.
상태 방정식: (1) 현재 상태의 수요자가 전 분기보다 많으면 사람을 고용해야 한다. 그래서 자금 비용은 전 분기의 최저 소비 + 이번 분기의 신규 고용비 + 이번 분기의 수요자의 임금
(2) 반대로 지난 분기의 사람이 이번 분기보다 많으면 인원을 줄여야 한다.비용: 지난 분기의 최저 소비 + 이번 분기의 인원수 * 송환비 + 이번 분기의 인원수 * 임금
(1)dp[i-1][k]+(j-k)*hiring+j*salary에 대해;
          (2)   dp[i-1][k]+(k-j)*firing+j*salary;
둘 사이에서 최소치를 찾아내면 dp[i][j]이고 마지막으로 최소치를 찾으면 된다.
AC 코드:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int dp[20][500];//* i    j  ;
int hiring , salary , firing; //*    ,  ,    ;
int num[13];//*    
int main()
{
    int month ;
    while(cin>>month, month)
    {
        memset(dp,0,sizeof(dp));
        memset(num , 0  ,sizeof(num));
        int maxi = - 1 ;
        cin>>hiring>>salary>>firing;
        for(int i = 1 ; i <=month ;i++)
        {
            cin>>num[i];//*       ;
            if(maxi<num[i])
            {
                maxi = num[i]; //*         ;
            }
        }

        for(int i= num[1] ; i<=maxi;i++) //*      ;
        {
            dp[1][i] = i*hiring + i*salary; //*        
        }
        int mini , cost ;
        for(int i= 2 ; i<= month ; i++)
        {
            for(int j = num[i] ; j<=maxi ; j++)
            {
                mini = 9999999 ;
                for(int k = num[i-1] ; k <=maxi ; k++)
                {
                    if(k<=j)
                        cost = dp[i-1][k]+(j-k)*hiring+j*salary;
                    else cost =  dp[i-1][k]+(k-j)*firing+j*salary;
                    if(mini >cost )
                        mini = cost ;
                }
                dp[i][j] = mini ;
            }
        }
        mini = 99999999 ;
        for(int i = num[month]; i<=maxi;i++)
        {
            if(dp[month][i] < mini )
            {
                mini = dp[month][i] ;
            }
        }

        cout << mini <<endl;
    }
    return 0 ;
}

좋은 웹페이지 즐겨찾기