UVa:907 Winterim Backpacking Trip

来源:互联网 发布:济南程序员工资 编辑:程序博客网 时间:2024/05/01 12:44

第200个AC。

 

最大值最小化的问题。可以用DP也可用二分做。

 

dp[i][j]表示从j个数字中切i次所得的最小的最大值。

dp[i][j]=min{max(dp[i-1][k],s[k-j])}  s[k-j]表示k到j的和 其中 1<=k<j

 

一开始以为k的范围是i+1到j,这里WA了一次。

 

DP:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define INF 0x7f7f7f7fusing namespace std;int dp[305][605];int a[605];int sum[605];int main(){    int N,K;    while(scanf("%d%d",&N,&K)!=EOF)    {        memset(dp,0,sizeof(dp));        memset(a,0,sizeof(a));        memset(sum,0,sizeof(sum));        for(int i=1; i<=N+1; ++i)        {            scanf("%d",&a[i]);            dp[0][i]=sum[i]=sum[i-1]+a[i];        }        for(int i=1; i<=K; ++i)            for(int j=1; j<=N+1; ++j)            {                int mn=INF;                for(int k=1; k<=j; ++k)                    mn=min(mn,max(dp[i-1][k],sum[j]-sum[k]));                dp[i][j]=mn;            }        printf("%d\n",dp[K][N+1]);    }    return 0;}

 

 

速度更快一些的二分法:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define INF 0x7f7f7f7fusing namespace std;int N,K;int a[605];bool Judge(int val){    int sum=0,n=0;    for(int i=1; i<=N+1; ++i)    {        if(a[i]>val) return false;        else        {            if(sum+a[i]<=val)                sum+=a[i];            else            {                n++;                sum=a[i];            }        }    }    if(sum<=val) n++;    if(n-1>K) return false;    else return true;}int Bsearch(int low,int high){    int mid;    while(low<high)    {        mid=(low+high)/2;        if(Judge(mid)) high=mid;        else low=mid+1;    }    return low;}int main(){    while(scanf("%d%d",&N,&K)!=EOF)    {        memset(a,0,sizeof(a));        int sum=0;        for(int i=1; i<=N+1; ++i)        {            scanf("%d",&a[i]);            sum+=a[i];        }        int ans=Bsearch(0,sum);        printf("%d\n",ans);    }    return 0;}


 

原创粉丝点击