零线火线 (powerline)

零线火线 (powerline)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

左手抓零线,右手抓火线,卒不卒? —— 某物理老师激情讲课

花生 一直很喜欢玩零线和火线。然而大家都知道,玩电线是十分危险的,若同时接触零线和火线,电流将直接通过心脏,非常危险。所以 花生 一直都带着橡胶手套玩电线。

但是带着橡胶手套玩起来很没有手感啊!

于是 花生 去学习了超能力 —— 肉体再生,这样就不用怕触电啦。

这个能力具体是这样的:

能力者每受到一次伤害,就会积累一点能量。每次使用能力,就会使用所积累的所有能量,恢复15×能量点数的生命值,并且相邻两次使用的时间至少要有 C D CD CD 秒的间隔, C D CD CD 的值由能力者的能力强度而定,能力越强 C D CD CD 值越小。

花生 的初始生命值为 H P HP HP(生命值无上限),他将要玩 n n n 秒的电线,每秒会受到一次伤害,第i秒的伤害值为 a i a_i ai。任何时刻,若 H P ≤ 0 HP≤0 HP0,则视为死亡。

花生 现在想知道,自己最少要把 C D CD CD 降低到多少,才可以安全地玩电线。

输入

第一行两个整数 n , H P n,HP n,HP,表示 花生 玩电线的时间与初始生命值。

第二行 n n n 个整数,为 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an

输出

共一行。

C D CD CD 没有上界,则输出 Peanut can play with the wires at will.;若无论如何都无法安全的玩电线,则输出 -1

否则输出这个最大的 C D CD CD 值。

样例输入

【样例1】

7 30
20 5 30 4 10 5 20

【样例2】

5 10
1 4 2 1 1

样例输出

【样例1】

2

【样例2】

Peanut can play with the wires at will.

提示

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 500 , 0 ≤ a i ≤ 2000 1≤n≤500,0≤ai≤2000 1n5000ai2000

思路

d p [ i ] dp[i] dp[i] 表示到 第 i i i 时刻剩下多少生命值,用类似 01 01 01 背包的思路转移
二分 C D CD CD 的值

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
typedef long long ll;
template <typename T>
inline void read(T &x) {
    x = 0;
    static int p;
    p = 1;
    static char c;
    c = getchar();
    while (!isdigit(c)) {
        if (c == '-')p = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 1) + (x << 3) + (c - 48);
        c = getchar();
    }
    x *= p;
}
template <typename T>
inline void print(T x) {
    static int cnt;
    static int a[50];
    cnt = 0;
    do {
        a[++cnt] = x % 10;
        x /= 10;
    } while (x);
    for (int i = cnt; i >= 1; i--)putchar(a[i] + '0');
    puts("");
}
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const int maxn =5e5+10;
int n,np;
int a[maxn];
int dp[maxn];
inline bool check(int x) {
    memset(dp, 0, sizeof dp);
    dp[0] = np;
    for (int i = 1; i <= n; ++i) {
        if (a[i] < np) {
            dp[i] = max(dp[i], np - a[i] + i * 15);
        }
        for (int j = i - x; j >= 1; --j) {
            if (dp[j] > a[i] - a[j])
                dp[i] = max(dp[i], dp[j] - (a[i] - a[j]) + (i - j) * 15);
        }
    }
    for (int i = 1; i <= n; ++i) {
        if (dp[i] && dp[i] - (a[n] - a[i]) > 0) {
            return 1;
        }
    }
    return 0;
}
inline void work() {
    scanf("%d %d", &n, &np);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        a[i] += a[i - 1];
    }
    int l = 1, r = n, ans =0;
    while (l <= r) {
        int mid = l + r >> 1;
        if (check(mid)) {
            ans = mid;
            l = mid + 1;
        } else r = mid - 1;
    }
    if (ans == n) printf("Peanut can play with the wires at will.\n");
    else if (ans == 0) printf("-1\n");
    else printf("%d\n", ans);
}
int main() {
    int T = 1;
    //read(T);
    while (T--) {
        work();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值