hdu 5653 Bomber Man wants to bomb an Array dp

问题描述
给一个长度为 NN 的一维格子和一些炸弹的位置,请你计算 “最大总破坏指数”。

每个炸弹都有向左和向右的破坏力,如果一个炸弹向左和向右的破坏力分别为 LLRR,
那么该炸弹将炸毁 L + R + 1L+R+1 个格子(左边LL个,炸弹所在格子,右边RR个)。
破坏指数的计算方式为:所有炸弹炸毁的格子数的乘积。假设第 ii 个炸弹炸毁了 X_iXi个格子,
那么总破坏指数就是 X_1 * X_2 * .... X_mX1X2....Xm。

现在告诉你每个炸弹的位置,你需要计算 最大的总破坏指数,注意:每个格子最多只允许被炸一次。
输入描述
多组测试数据,第一行为一个整数 T(T \leq 11)T(T11)。
每组测试数据第一行为两个整数 N, M(1 \leq N \leq 2000, 1\leq M \leq N)N,M(1N2000,1MN),分别表示格子总数和炸弹总数 。
第二行是 MM 个互不相同的数表示每个炸弹所在的位置。
输出描述
对于每组测试数据,输出 floor(10^6 * log2(最大破坏指数)) (floor表示向下取整)。
输入样例
2
10 2
0 9
10 3
0 4 8
输出样例
4643856
5169925



先不考虑将结果乘以 1e6。 设 dp[i] 为从前 i 个格子的状态可以获得的最大破坏指数。那么我们可以枚举每个炸弹,该炸弹向左延伸的距离和向又延伸的距离。 设第 i 个炸弹破坏区间为 [l, r], 则 dp[r] = dp[l - 1] * log2(r - l + 1)。答案就是 dp[n - 1]。不要忘记最后要向下取整。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m;
int pos[2010];
double dp[2010];

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        double ans = 0;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i++)
        {
            scanf("%d", &pos[i]);
            pos[i] ++;
        }
        sort(pos + 1, pos + 1 + m);
        pos[m + 1] = 2005;
        memset(dp, 0, sizeof(dp));
        dp[pos[1]] = log(pos[1]) / log(2);
        for (int i = pos[1] + 1; i < pos[2]; i++)
            dp[i] = log(i) / log(2);
        for (int i = 2; i <= m; i++)
            for  (int j = pos[i - 1]; j < pos[i]; j++)
                for (int k = pos[i]; k < pos[i + 1]; k++)
                {
                    dp[k] = max(dp[k], dp[j] + log(k - j) / log(2));
                }
        printf("%I64d\n", (long long)(dp[n] * 1e6));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值