hdu1158

来源:互联网 发布:重庆亿展网络招聘信息 编辑:程序博客网 时间:2024/06/12 10:04

说来惭愧这题想了好久都没与AC,最后看了下别人的思路,感觉和我的差不多,但是还是没能AC就看了下代码,才明白自己处理事情没有处理好导致细节性的错误,其实我觉得座ACM很大的忌讳就是不要浮躁,因为这里面细节性考的太严了,很多时候只是自己很小的一点没有考虑清楚就会导致WA,而自己又不能沉下心来思考。所以说心静是非常需要的,既然WA了,就说明你那个地方没有想明白,还需要仔细考虑一下。下面讲讲这题的思路:

        这题很像是背包的题,大意是某施工场地需要找人,每个月的人数是固定的,雇佣,开除一个人都是有相应的代价,每个没有被开除的人每个月还有固定工资,最后需要你给出所需付出的最少的钱。

         无非我们想到的就是某一个月的人数裁或不裁的决定,每一个现在的决定取决于前面的人数,也就是现在的状态受到前面的限制,然而因为我们在递推的时候如果不知道前一个月的人数是很难决定的,所以我们需要记录上一个月的人数,做法:

           我们以need[i]表示每个月需要的人数,从第一个月从后走,当走到第i(i>=2)个月的时候,需要知道从上一个月到这个月过度最佳的人数,这个人数可以限制在上一个月的人数need[i-1]和这个月的人数need[i]之间,那么这个月的人数需要多少?固定在need[i]到need[i+1]之间。。。。。这样的处理很麻烦,那么我们就将所有的月份最大的值Maxneed找出来,直接从本月到最大的值就可以了。转移方程   if(k<j)
                        f[i][j]=min(f[i][j],f[i-1][k]+j*gz+(j-k)*hire);
                 else f[i][j]=min(f[i][j],f[i-1][k]+j*gz+(k-j)*fire);;f[i][j]是第i个月需要j名工人,他的值表示第i个月需要j名工人之后加上前i-1个月所需要的资金总和,f[i-1][k]表示上个月所留下来的工人他的范围是上个月的需要人数need[i-1]到最大人数(因为你无法预知什么时候人数需要最好)所需要的资金总和,j是这个月的人数。后面就是雇佣或者开除人的代价,当然在此之前f[i][j]初始化成很大的数字。

           看懂了上面的话就是一句话:从上个月的需要人数到最大人数分别向这个月需要人数到最大人数进行递推。到最后筛选一下就好,下面提供一个代码:

#include<iostream>
using namespace std;
#include<stdio.h>
#include<cstdlib>
#include<cmath>
#include<string.h>
int f[15][10000];
int fire,hire,gz;
int min(int m,int n)
{
    return m<n?m:n;
}
int main()
{
    int N;
    int need[15];
    int maxneed,i,j,k;
    while(cin>>N,N)
    {
        maxneed=0;
        int max=1<<30;
        maxneed=0;
        cin>>hire>>gz>>fire;
        for(i=0;i<N;i++)
        {
            scanf("%d",&need[i]);
            if(maxneed<need[i])
                maxneed=need[i];
        }
      
       memset(f,0,sizeof(f));
       for(i=need[0];i<=maxneed;i++)f[0][i]=(hire+gz)*i;//第一个月人数虽然已经固定,但是为了后面处理的方便我们都处理一下。
  
       for(i=1;i<N;i++)
       {
         for(j=need[i];j<=maxneed;j++)                  //j表示本月人数可以达到的范围
         {
             f[i][j]=1<<30;
             for(k=need[i-1];k<=maxneed;k++)                     //k表示上个月的人数可以到达的范围
             {
                // cout<<"hao2"<<endl;
                 if(k<j)
                    f[i][j]=min(f[i][j],f[i-1][k]+j*gz+(j-k)*hire);
                 else f[i][j]=min(f[i][j],f[i-1][k]+j*gz+(k-j)*fire);
             }
          
         }
       }
        for(k=need[N-1];k<=maxneed;k++)
            {
                if(f[N-1][k]<max)
                max=f[N-1][k];
               
            }
            cout<<max<<endl;
    }
    return 0;
}

0 0
原创粉丝点击