返回顶部
大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

Storage Keepers UVA - 10163

先二分最小的安全系数,在dp

dp[i][j]表示前i个人管j个仓库的最小值

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;

const int maxn = 1e2+12;

const int maxm = 35;

int n,m,p[maxm],f[maxm][maxn];

int ansmax,ansmin;

bool check(int mid) {
    memset(f,0x3f,sizeof(f));
    for(int i=0;i<=m;i++)f[i][0]=0;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++) {
            for(int k=j;k>=0;k--) {
                if(j!=k&&p[i]/(j-k)<mid) break;
                f[i][j]=min(f[i][j],f[i-1][k]+(j==k?0:p[i]));
            }
        }
    return f[m][n]<inf?true:false;
}

int main() {
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF&&n&&m) {
        ansmax=0;ansmin=inf;
        int l=0,r=-1;
        for(int i=1;i<=m;i++) scanf("%d",&p[i]),r=max(r,p[i]);
        while(l<=r) {
            int mid=(l+r)>>1;
            if(check(mid)) {ansmax=mid;l=mid+1;ansmin=f[m][n];}
            else r=mid-1;
        }
        if(ansmax) printf("%d %d\n",ansmax,ansmin);
        else printf("0 0\n");//特判
    }
    return 0;
}

 

posted @ 2019-05-19 16:13  plysc  阅读(134)  评论(0编辑  收藏  举报