CodeFoces #377(732A|732B|732C|732D|732E)|贪心

来源:互联网 发布:客户数据分析的流程 编辑:程序博客网 时间:2024/05/17 07:42

这是贪心大赛的节奏。。。

732A Buy a Shovel

题目大意

一件商品k元,你身上有无数多个10元硬币和r(1r9)元硬币,问买多少件商品你才可以刚好使用你身上的硬币购买而不需要找零。

题解

显然商品件数不会超过10件(10件时可以只使用10元硬币),且只k的个位数有关。

#include <cstdio>int main() {    int k, r, i;    scanf("%d%d", &k, &r);    for (i = 1; i <= 10; ++i)        if (k * i % 10 == r || k * i % 10 == 0)            break;    printf("%d", i);    return 0;}

732B Cormen — The Best Friend Of a Man

题目大意

狗狗每连续的2天总的要散步k次(即ai+ai+1k,ai+1+ai+2k),已知主人每天已确定的散步次数,问最少要额外去散步使得能满足k次的要求。

题解

显然对于连续的两天aiai1,若ai+ai1<k,那么额外的散步次数显然加到ai比较好,因为这样我们就可以同时服务于ai+1

#include <cstdio>#define max(i,j) ((i)>(j)?(i):(j))#define FOR(i,j,k) for(i=j;i<=k;++i)const int N = 512;int a[N];int main() {    int n, k, i, d, t = 0;    scanf("%d%d", &n, &k);    FOR(i,1,n) scanf("%d", a + i);    FOR(i,2,n) {        d = max(0, k - a[i] - a[i - 1]);        a[i] += d, t += d;    }    printf("%d\n", t);    FOR(i,1,n) printf("%d ", a[i]);    return 0;}

732C Sanatorium

题目大意

一个人旅宿酒店(开始和结束都在用餐时间之外),但他的用餐记录(早餐,中餐,晚餐)不全(比如早餐记录少了2次),问他最少少计了几次用餐。比如第一天早餐后中餐前到酒店,第3天中餐后晚餐前离开,那么本应该早餐2次,中餐3次,晚餐2次,如果用餐记录为2,1,2,那么用餐记录就少了2次。(写到这里我已经看不懂“餐”了)

题解

首先,我们可以直接假定用餐记录中最大的是“真实的”,否则无法满足最少漏记录数,又注意到3餐记录数差不会超过1,然后就没有然后了。

#include <cstdio>#define max(i,j) ((i)>(j)?(i):(j))typedef long long ll;int main() {    ll b, d, s;    scanf("%I64d%I64d%I64d", &b, &d, &s);    ll ma = max(max(b, d), s);    printf("%I64d", max(ma - b - 1, 0ll) + max(ma - d - 1, 0ll) + max(ma - s - 1, 0ll));    return 0;}

732D Exams

题目大意

要考试了,已知有m门课要考试,每门课考试要准备a[i]天才能通过,已知考试安排d,其中d[i]是课编号,若为0表示这天不考试。问你至少花多少天可以通过所有考试。

题解

由于存在考试时间的选择问题,我们可以先透支时间考试,然后后面再补回来就好啦。
首先我们先把能考的都先考了,然后再调整考试时间,遇到了考试,如果准备时间已经透支了,那么就把当前考试延后到这次考,使得准备时间足够。当然如果没有考试可以延后了就-1。

#include <cstdio>#define FOR(i,j,k) for(i=j;i<=k;++i)const int N = 100005;int a[N], d[N], c[N];int main() {    int i, n, m;    scanf("%d%d", &n, &m);    FOR(i,1,n) scanf("%d", d + i), c[d[i]] = 1;    FOR(i,1,m) scanf("%d", a + i);    int spare = 0, subject = 0;    c[0] = 0; a[0] = -1;    FOR(i,1,n+1) {        spare -= a[d[i]];        subject += c[d[i]];        c[d[i]] = 0;        a[d[i]] = -1;        if (spare >= 0 && subject == m && d[i])            return printf("%d", i), 0;    }    return puts("-1"), 0;}

732E Sockets

题目大意

有一些电脑和电源,当电脑和电源的电压一致时就可以连接,一台电源只能连一台电脑,一台电脑只能连一台电源,有些电脑和电源的电压不匹配,通过向电源外挂适配器可以使电源电压从si变为si2,适配器可以串接,也就是说,一台99V的电源,外挂6个变压器就可以变成2V。问接到电源的电脑台数最大时,适配器最少可以有多少。

题解

由于电源和电脑是一对一连接的,故一旦我们可以连接一台电源和电脑,我们就连接。注意到若要最小化适配器的个数,我们就应该能不用适配器就不用适配器,故我们先不用适配器,连接一次电脑,用1个适配器,连接一次电脑……

#include <cstdio>#include <algorithm>using std::sort;#define FOR(i,j,k) for(i=j;i<=k;++i)const int N = 200005;int n, m;struct Data {    int i, v;    bool operator <(const Data &b) const {        return v < b.v;    }} p[N], s[N];int b[N], d[N], bcnt = 0, ad = 0;void match(int adapter) {    int i = 1, j = 1;    while (i <= n && j <= m) {        if (b[p[i].i] || p[i].v < s[j].v) ++i;        else if (d[s[j].i] || p[i].v > s[j].v) ++j;        else if (p[i].v == s[j].v) {            b[p[i].i] = s[j].i, bcnt++;            d[s[j].i] = adapter + 1;            ad += adapter;        }    }}int main() {    int i, j;    scanf("%d%d", &n, &m);    FOR(i,1,n) scanf("%d", &p[i].v), p[i].i = i;    sort(p + 1, p + 1 + n);    FOR(i,1,m) scanf("%d", &s[i].v), s[i].i = i;    sort(s + 1, s + 1 + m);    match(0);    FOR(i,1,31) {        FOR(j,1,m) s[j].v = (s[j].v + 1) / 2;        match(i);    }    printf("%d %d\n", bcnt, ad);    FOR(i,1,m) printf("%d ", (d[i] == 0 ) ? 0 : (d[i] - 1));    putchar('\n');    FOR(i,1,n) printf("%d ", b[i]);    return 0;}
0 0