HDU5653 Bomber Man wants to bomb an Array. DP

Bomber Man wants to bomb an Array.

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 246    Accepted Submission(s): 82


Problem 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 i th 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 i th bomb destroys Xi blocks then TotalImpact=X1X2....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
1. Bomber Man wants to plant a bomb at every bombing location.
2. Bomber Man wants to destroy each block with only once.
3. Bomber Man wants to destroy every block.

 

Input
There are multi test cases denote by a integer T(T20) 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)).

Hint:
Sample 1:



Sample 2:

 

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

Sample Output
  
  
4643856 5169925
 

Source
 考虑DP,设dp[i][j]=序列位置i到j能得到的最大的破坏值(是log2之后的值)
dp[i][j]=max(dp[i][j],log2[k-i]+dp[k][j]) i<k<=j 并且保证[i,k-1],[k,j]内都有炸弹。
记忆化搜索一下。
还有就是log2函数速度有点慢,所以要预处理出[1,2000]以内的log2值Log2[],不然会TLE。


/****************
*PID:hdu5653
*Auth:Jonariguez
*****************
事实证明Log2太慢,需要预处理。
*/
#define lson k*2,l,m
#define rson k*2+1,m+1,r
#define rep(i,s,e) for(i=(s);i<=(e);i++)
#define For(j,s,e) For(j=(s);j<(e);j++)
#define sc(x) scanf("%d",&x)
#define In(x) scanf("%I64d",&x)
#define pf(x) printf("%d",x)
#define pfn(x) printf("%d\n",(x))
#define Pf(x) printf("%I64d",(x))
#define Pfn(x) printf("%I64d\n",(x))
#define Pc printf(" ")
#define PY puts("YES")
#define PN puts("NO")
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef int Ll;
Ll quick_pow(Ll a,Ll b,Ll MOD){a%=MOD;Ll res=1;while(b){if(b&1)res=(res*a)%MOD;b/=2;a=(a*a)%MOD;}return res;}

const int maxn=2000+10;
const double INF=1000000;
int vis[maxn][maxn],p[maxn],sum[maxn];
double dp[maxn][maxn],Log2[maxn];
double DP(int x,int y){
    if(x>=y) return 0;
    if(vis[x][y]) return dp[x][y];
    vis[x][y]=1;
    double &ans=dp[x][y];
    ans=0;
    if(sum[y]-sum[x-1]==1)
        return ans=Log2[y-x+1];
    int cnt=0,i=x;
    while(p[i]==0) i++;
    if(i>y) return ans=-INF;     //区间内无炸弹则返回负无穷
    i++;
    for(;i<=y;i++){
        ans=max(ans,Log2[i-x]+DP(i,y));
        if(p[i]) break;          //[x,i-1]内保证只有一个炸弹,所以再次遇到炸弹则停止,下同。
    }
    i=y;
    while(p[i]==0) i--;
    i--;
    for(;i>=x;i--){
        ans=max(ans,Log2[y-i]+DP(x,i));
        if(p[i]) break;
    }
    return ans;
}

int main()
{
    int i,j,n,T;
    for(i=1;i<=2001;i++)
        Log2[i]=log2(i);
    scanf("%d",&T);
    while(T--){
        int m;
        sc(n);sc(m);
        memset(vis,0,sizeof(vis));
        memset(p,0,sizeof(p));
        for(i=1;i<=m;i++){
            int x;
            sc(x);x++;
            p[x]=1;
        }
        sum[0]=0;
        for(i=1;i<=2001;i++)
            sum[i]=sum[i-1]+p[i];
        double res=DP(1,n);
        printf("%I64d\n",(LL)floor(1000000.0*res));
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值