uva 10163 - Storage Keepers

首先是简单的贪心:实际上一个箱子只能由一个人来看管,这样才能达到最优解。

L[i][j]代表从(i,n-1)keeper中选人看管j个箱子的最大保险值

Y[i][j]代表相应的最小工资

12ms:

#include <iostream>

#include<cstdio>

#include<cstring>

#define INF 0x3f3f3f3f

using namespace std;

int L[35][105],Y[35][105],n,m,P[35];

int dp1(int i,int j)

{

    if(L[i][j]!=-1)

    return L[i][j];

    if(j==0)

    return L[i][j]=INF;

    if(i==m)

    return L[i][j]=0;



    int k=min(j,P[i]);

    for(;k>=0;k--)

    if(k)

    L[i][j]=max(L[i][j],min(P[i]/k,dp1(i+1,j-k)));

    else

    L[i][j]=max(L[i][j],dp1(i+1,j));

    return L[i][j];

}

int dp2(int i,int j)

{

    if(Y[i][j]!=-1)

    return Y[i][j];



    if(j==0)

    return Y[i][j]=0;

    if(i==m)

    return Y[i][j]=INF;

    Y[i][j]=INF;

    int k=min(j,P[i]);

    for(;k>=0;k--)

    if(k)

    {

        if(L[0][n]<=min(P[i]/k,L[i+1][j-k]))

        Y[i][j]=min(Y[i][j],P[i]+dp2(i+1,j-k));

    }

    else

    {

        if(L[0][n]<=L[i+1][j])

        Y[i][j]=min(Y[i][j],dp2(i+1,j));

    }

    return Y[i][j];

}

int main()

{

    while(scanf("%d%d",&n,&m),n+m)

    {

        memset(Y,-1,sizeof(Y));

        memset(L,-1,sizeof(L));

        for(int i=0;i<m;i++)

        scanf("%d",&P[i]);

        dp1(0,n);

        dp2(0,n);

        if(L[0][n]==0)

        puts("0 0");

        else

        printf("%d %d\n",L[0][n],Y[0][n]);

    }

    return 0;

}

  

你可能感兴趣的:(ora)