O

题目大意:

第一行一个n,表示共n个月份,然后第二行分别表示一个工人的聘请工资,月薪水,解雇工资。第三行是n个月每个月需要的工人的最少数目。然后求最少花费

题解:

dp[i][j] 表示第i个月聘请j个人需要的最少花费。

状态是怎么转移的呢?

当第i-1个月聘请k个人时。

如果k<j。需要聘请新人 dp[i][j]=dp[i-1][k]+hire*(j-k)+salary*j;

否则 。。需要解雇人员 dp[i][j]=dp[i-1][k]+fire*(k-j)+salart*j;

注意:最后一个月聘请的人不需要解雇。。。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1E3+7; 
const ll INF=1e18+7;
ll dp[N][N];
ll arr[N]; 
int main(){
    ll n;
    while(cin>>n,n){
        ll hire,salary,fire;
        
        cin>>hire>>salary>>fire;
        ll maxx=0;
        
        for(ll i=1;i<=n;i++){
            cin>>arr[i];
            maxx=max(arr[i],maxx);
        }
        
        for(ll i=0;i<=n;i++)
            for(ll j=0;j<=maxx;j++)
                dp[i][j]=INF;
        
        for(ll i=arr[1];i<=maxx;i++)  dp[1][i]=hire*i+salary*i;
        
        for(ll i=2;i<=n;i++){
            for(ll j=arr[i];j<=maxx;j++){
                for(ll k=arr[i-1];k<=maxx;k++){
                    if(j>k) dp[i][j]=min(dp[i][j],dp[i-1][k]+hire*(j-k)+salary*j);
                    else     dp[i][j]=min(dp[i][j],dp[i-1][k]+fire*(k-j)+salary*j);
                }
            }
        }
        
        ll ans=INF;
        
        for(ll i=arr[n];i<=maxx;i++) ans=min(ans,dp[n][i]);
        
        cout<<ans<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Accepting/p/12463535.html