牛客小白赛53场(补题)

D:Breezing

(动态规划)

思路:存在最优方案,之中每一个数要么是1,要么是Bi,(猜想的结论,不会证明)
dp[n][2]
dp[i][j] 表示第 i 个数结尾,第 i 个数为1(j = 1) or 第 i 个数为 Bi 时的最大可爱值。
当前的状态是由前两个状态转移得到(分别为前一个状态取1,或取 Bi)
当前的状态还有两种(分别为前一个状态取1,或取 Bi)

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;

int f[N][2];
int n, b[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n ; i ++ ) cin >> b[i];
    for (int i = 2; i <= n ; i ++ ) {
        f[i][0] = max(f[i - 1][0] + abs(1 - 1), f[i - 1][1] + abs(1 - b[i - 1]));
        f[i][1] = max(f[i - 1][0] + abs(b[i] - 1), f[i - 1][1] + abs(b[i] - b[i - 1]));
    }
    int res = max(f[n][0], f[n][1]);
    cout << res << endl;
    return 0;
}

E:Calling

(模拟)

直接官方思路:
对于边长为 6 的正方形纸片:显然一个纸片就要一个框,所以答案加 f 。
对于边长为 5 的正方形纸片:显然一个纸片就要一个框,所以答案加 e。
对于边长为 4 的正方形纸片:显然一个纸片就要一个框,所以答案加 d。
对于边长为 3 的正方形纸片:一个框能放 4 个,所以答案加 ceil(c / 4)向上取整
对于边长为 2 的正方形纸片:
我们可以把他和边长为 4 的放在一起,不难发现在每个框还可以放得下 5 个。
放完了之后可以把他和边长为 3 的放在一起。
如果还有多出来 1 个边长为 3 的,那么就可以放 5 个边长为 2 的。
如果还有多出来 2 个边长为 3 的,那么就可以放 3 个边长为 2 的。
如果还有多出来 3 个边长为 3 的,那么就可以放 1 个边长为 2 的。
如果还有多的,就单独放。
对于边长为 1 的正方形纸片:哪里有空就往哪放,如果还有多的就单独放。

#include <bits/stdc++.h>
using namespace std;

double s, a, b, c, d, e, f;
int t;

int main() {
    cin >> t;
    while ( t -- ) {
        cin >> s;
        cin >> a >> b >> c >> d >> e >> f;
        int res = 0;
        res = f + e + d + ceil(c / 4); // ceil 向上取整
        int putb = d * 5; // 放4的框,可以放多少个 2 * 2的
        if ((int)c % 4 != 0) {
            if ((int)c % 4 == 1) putb += 5; // 一个框里面放1个4 * 4的,剩余空间就可以放5个2 * 2的
            if ((int)c % 4 == 2) putb += 3; // 一个框里面放2个4 * 4的,剩余空间就可以放3个2 * 2的
            if ((int)c % 4 == 3) putb += 1; // 一个框里面放3个4 * 4的,剩余空间就可以放1个2 * 2的
        }
        if (b > putb) res += ceil((b - putb) / 9); // 2 * 2的还有剩余
        int used = 6 * 6 * f + 5 * 5 * e + 4 * 4 * d + 3 * 3 * c + 2 * 2 * b; // 被使用过的面积和
        int puta = res * 6 * 6 - used; // 除a本身以外,其他框中可以放a的总数
        if (puta < a) { // 说明除放入其他框的a,a还有剩余,要自己一种的放入框了
            res += ceil((a - puta) / 6 * 6);
        }
        if (res <= s) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}

F:Freezing

(状压dp,优化)

我的评价是好难,还不是很懂,需要再思考思考~
请添加图片描述

// 这也太难了吧,还得思考思考~
#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;
int f[1 << 8][1 << 8];
char s[17];

int main() {
    int n, m;
    cin >> n >> m;
    int res = 0;
    while ( n -- ) {
        cin >> s;
        int a = 0;
        for (int i = 0; i < m ; i ++ ) {
            a = (a << 1) | (s[i] == 'o'); // 将输入的s转化为二进制数,o为1,h为0
        }
        int x = a >> 8, y = a & 255, tmp = 1; // x为高八位,y为低八位,初始tmp为1,队列为空(不懂)
        for (int i = 0; i < (1 << 8) ; i ++ ) { // 这样一来,hi,li都与x,y不同,的方案数,满足题意
            if (!(x & i)) {
                (tmp += f[i][y]) %= mod;
            }
        }
        (res += tmp) %= mod; // 累加方案数
        for (int i = 0; i < (1 << 8) ; i ++ ) { // 更新一下f,阿巴阿巴~
            if (!(y & i)) {
                (f[x][i] += tmp) %= mod;
            }
        }
    }
    cout << res << endl;
    return 0;
}

妙啊,简直就是妙蛙种子吃了妙脆角走进了米奇妙妙屋,妙到家了~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值