NOIP2018 初赛

题目
#include <cstdio>
#include <algorithm>
using namespace std;

const int Inf = 1000000000;
const int threshold = 50000;
const int maxn = 1000;

int n, a[maxn], b[maxn];
bool put_a[maxn];
int total_a, total_b;
double ans;
int f[threshold];

int main()
{
    scanf("%d", &n);
    total_a = total_b = 0;
    for (int i = 0; i < n; ++i)
    {
        scanf("%d%d", a + i, b + i);
        if (a[i] <= b[i]) total_a += a[i];
        else total_b += b[i];
    }
    ans = total_a + total_b;
    total_a = total_b = 0;
    for (int i = 0; i < n; ++i)
    {
        if (____(1)____)//0.95 * a[i] <= b[i]
        {
            put_a[i] = true;
            total_a += a[i];
        }
        else
        {
            put_a[i] = false;
            total_b += b[i];
        }
    }
    if (____(2)____)//total_a >= threshold
    {
        printf("%.2f", total_a * 0.95 + total_b);
        return 0;
    }
    f[0] = 0;
    for (int i = 1; i < threshold; ++i)
        f[i] = Inf;
    int total_b_prefix = 0;
    for (int i = 0; i < n; ++i)
    {
        if (!put_a[i])
        {
            total_b_prefix += b[i];
            for (int j = threshold - 1; j >= 0; --j)
            {
                if (____(3)____ >= threshold && f[j] != Inf)//total_a + j + a[i]
                    ans = min(ans, (total_a + j + a[i]) * 0.95 + ____(4)____);//f[j] + total_b - total_b_prefix
                f[j] = min(f[j] + b[i], j >= a[i] ? ____(5)____ : Inf);//f[j - a[i]]
            }
        }
    }
    printf("%.2f", ans);
    return 0;
}

dp “已经选择全部0.95a<b的a,但∑a<50000”的情况,

f[j]表示“从那些0.95a>b(不优的a)的(a,b)二元组中再选出∑a=j时,所剩下最小的Σb”。

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注