HDU 5653 Bomber Man wants to bomb an Array. dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5653
题意:
Description

Given an array and some positions where to plant the bombs, You have to print the Total Maximum Impact.

Each Bomb has some left destruction capability L and some right destruction capability R which means if a bomb is dropped at ith location it will destroy L blocks on the left and R blocks on the right.
Number of Blocks destroyed by a bomb is L+R+1
Total Impact is calculated as product of number of blocks destroyed by each bomb.
If ith bomb destroys Xi blocks then TotalImpact=X1∗X2∗….Xm

Given the bombing locations in the array, print the Maximum Total Impact such that every block of the array is destoryed exactly once(i.e it is effected by only one bomb).
Rules of Bombing

Bomber Man wants to plant a bomb at every bombing location.
Bomber Man wants to destroy each block with only once.
Bomber Man wants to destroy every block.

Input

There are multi test cases denote by a integer T(T≤20) in the first line.

First line two Integers N and M which are the number of locations and number of bombing locations respectivly.
Second line contains M distinct integers specifying the Bombing Locations.

1 <= N <= 2000

1 <= M <= N
Output

as Maximum Total Impact can be very large print the floor(1000000 * log2(Maximum Total Impact)).
Sample Input

2
10 2
0 9
10 3
0 4 8
Sample Output

4643856
5169925

题意:
一个长为n的地方,有m个炸弹。

每个炸弹可以炸掉l+r+1的位置,表示这个炸弹炸掉左边l个,右边r个,自己所在的一个

然后他们炸完之后,的贡献就是a[1]a[2]….*a[n]

a[i]表示第i个炸掉了多少个

解法:
DP。dp[i][j]表示前i个炸弹爆炸,最右界是j,所对应的最大破坏力。
我们枚举炸弹
枚举右爆炸范围
枚举左爆炸范围
就可以更新dp[i][j]=max(dp[i-1][l-1]+log2(r-l+1))
答案就是dp[n][m]
看似枚举了三重n
这个复杂度其实只有n^2

//HDU 5653

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2005;
int n, m, a[maxn];
double dp[maxn][maxn];//dp[i][j]表示前i个炸弹爆炸,最右界是j,所对应的最大破坏力
double lg[maxn];
int main()
{
    for(int i = 1; i <= 2000; i++) lg[i] = log(i)/log(2);
    int T; scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        memset(a, 0, sizeof(a));
        memset(dp, 0, sizeof(dp));
        for(int i = 1; i <= m; i++) scanf("%d", &a[i]), ++a[i];
        a[0] = 0;
        sort(a+1, a+m+1);
        a[m+1] = n+1;
        dp[0][0] = 0;
        for(int i = 1; i <= m; i++){
            for(int j = a[i]; j <= a[i+1]-1; j++){
                dp[i][j] = 0;
                for(int k = a[i-1]+1; k <= a[i]; k++){
                    int len = j-k+1;
                    dp[i][j] = max(dp[i][j], dp[i-1][k-1]+lg[len]);
                }
            }
        }
        long long ans = floor(dp[m][n]*1000000);
        printf("%lld\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值