Storage Keepers UVA

来源:互联网 发布:淘宝首页热点 编辑:程序博客网 时间:2024/06/16 13:18

题目链接:点击打开链接

题目思路:还是挺好想的,先用一次dp找出最大安全系数,再用一次dp找到最小花费,第一次dp定义前i个人看守j个最大安全系数,第二为前i个人看守j个并且安全系数大与第一个dp求出来的值的最小花费,同学用贪心加二分写了第一问让我很不爽QAQ

ac代码:

#include<cstdio>#include<algorithm>#include<cstring>#include<cstring>#include<iostream>#include<sstream>#include<cmath>#include<vector>#define LL long long#define INF 0x3f3f3f3f#define eps 1e-6using namespace std;const int maxn = 1e7+6;int dp[1000][1005];int dp2[1000][1005];int n,m;int a[510];int cmp(int c,int d){    return c>d;}int main(){    while(~scanf("%d%d",&n,&m))    {        if(!n)            return 0;        for(int i = 1;i<=m;i++){            scanf("%d",&a[i]);        }        sort(a+1,a+m+1,cmp);            memset(dp,0,sizeof(dp));            for(int i = 0;i <= m;i++){                dp[i][0] = INF;            }            for(int i = 1;i<=m;i++){                for(int j = 1;j<=n;j++){                        dp[i][j] = dp[i-1][j];                    for(int k = 1;k<=j;k++)                        if(dp[i-1][j-k]!=0)                            dp[i][j] = max(dp[i][j],min(dp[i-1][j-k],a[i]/k));                   // cout<<dp[i][j]<<' '<<i<<' '<<j<<endl;                }            }            int sum = 0;            int ans = -1;            int pos;            ans = dp[m][n];         memset(dp2,INF,sizeof(dp2));        for(int i =0;i<=m;i++)            dp2[i][0] = 0;        for(int i=1;i<=m;i++)        {            for(int j=1;j<=n;j++)            {                dp2[i][j]=dp2[i-1][j];                for(int k=1;k<=j;k++)                    if((a[i]/k)>=ans)                       dp2[i][j]=min(dp2[i][j],dp2[i-1][j-k]+a[i]);            }         }            sum = dp2[m][n];            if(ans==0)                sum = 0;            cout<<ans<<' '<<sum<<endl;    }}


原创粉丝点击