【HDOJ 4968】 Improving the GPA

【HDOJ 4968】 Improving the GPA

动态规划里的背包问题。。比赛时候暴力做的 还好当时脑洞足。。。
暴力枚举
求最大值时初始n个成绩都为最大值所需的最小成绩–85 然后从第一个开始减 分数全都用掉时跳出 第一个减到60后第二个开始 以此类推
求最小值反向做即可 初始为最小值所需的最大成绩–64

背包方法 一维为当前成绩类数 二位为当前使用掉的分数(减去60 因为最小分为60 60之前都是无用空间)
初始dpmax -INF dpmin INF
dpmax[0][0] = dpmin[0][0] = 0;
for i 1->n
for j 0->40
for k 0->v
dpmax = max(dpmax[i][j],dpmax[i-1][j-k] + get(k));
dpmin = min(dpmin[i][j],dpmin[i-1][j-k] + get(k));

代码如下:

//暴力枚举
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>

using namespace std;

double Min(int x,int k)
{
    if(x <= 69) return 2.0;
    int i,j,rest = (x - 69)*k;
    double sum = 2.0*k;

    for(i = 1; i <= k; ++i)
    {
        for(j = 0; j < 3; ++j)
        {
            sum += 0.5;
            if(rest <= 5) return sum/k;
            rest -= 5;
        }
        sum += 0.5;
        if(rest <= 16) return sum/k;
        rest -= 16;
    }
}

double Max(int x,int k)
{
    if(x >= 85) return 4.0;
    int i,j,rest = (85 - x)*k;
    double sum = 4.0*k;

    for(i = 1; i <= k; ++i)
    {
        for(j = 0; j < 3; ++j)
        {
            sum -= 0.5;
            if(rest <= 5) return sum/k;
            rest -= 5;
        }
        sum -= 0.5;
        if(rest <= 10) return sum/k;
        rest -= 10;
    }
}

int main()
{
    int t,x,i,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&x,&k);
        printf("%.4lf ",Min(x,k));
        printf("%.4lf\n",Max(x,k));
    }
    return 0;
}
//dp背包
#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f

using namespace std;

double dp1[11][405],dp2[11][405];

double get(int k)
{
    return (k <= 9)? 2.0 : (k <= 14? 2.5: (k <= 19? 3.0: (k <= 24?  3.5: 4.0)));
}

void Minx(int v,int n)
{
    int i,j,k;
    for(i = 0; i <= n; ++i)
    {
        for(j = 0; j <= v*n; ++j)
        {
            dp1[i][j] = INF;
            dp2[i][j] = -INF;
        }
    }
    dp1[0][0] = dp2[0][0] = 0;
    for(i = 1; i <= n; ++i)
    {
        for(k = 0; k <= 40 ; ++k)
        {
            for(j = 0; j +k <= v*i; ++j)
            {
                dp1[i][j+k] = min(dp1[i][j+k],dp1[i-1][j] + get(k));
                dp2[i][j+k] = max(dp2[i][j+k],dp2[i-1][j] + get(k));
            }
        }
    }
}

int main()
{
    int t,v,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&v,&n);
        v = (v-60);
        Minx(v,n);
        printf("%.4lf %.4lf\n",dp1[n][v*n]/n,dp2[n][v*n]/n);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值