1. 程式人生 > >HDU5653 Bomber Man wants to bomb an Array. DP

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 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=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 BestCoder Round #77 (div.2)

 考慮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;
}