码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5653 Bomber Man wants to bomb an Array 简单DP

时间:2016-03-27 01:21:40      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:

题意:bc 77 div1 1003(中文题面)

分析:先不考虑将结果乘以 1e6。 设 dp[i] 为从前 i 个格子的状态可以获得的最大破坏指数。

那么我们可以枚举每个炸弹,该炸弹向左延伸的距离和向又延伸的距离。

设第 i 个炸弹破坏区间为 [l, r], 则 dp[r] = dp[l - 1] + log2(r - l + 1)。答案就是 dp[n - 1]。不要忘记最后要向下取整。

 

注:我对官方题解稍作解释,dp[i]代表前i个格子可以获得的最大破坏指数

但是更新的时候,需要注意,假设有 n 个炸弹,第 i 个炸弹的位置是o[i]

那么考虑处理到第i个炸弹,他能更新的dp[j]是有限制的,o[i]<=j<o[i+1],因为一个炸弹的爆炸区域不可能跨过另外一个炸弹

更新dp[j]的也dp[k]也是有限制的,o[i-1]<=k<=o[i],道理是一样的

然后看起来是三重循环,实际上很小

然后有一个小优化,事先把log2(1-2000)打出来,因为这个函数很慢

 

技术分享
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=2e3+5;
const int INF=0x3f3f3f3f;
int o[N];
double dp[N],val[N];
int main(){
    for(int i=1;i<=2001;++i)
      val[i]=log(i)/log(2);
    int T;
    scanf("%d",&T);
    while(T--){
      int n,m;
      scanf("%d%d",&n,&m);
      for(int i=1;i<=m;++i)
       scanf("%d",&o[i]),++o[i];
      sort(o+1,o+1+m); 
      memset(dp,0,sizeof(dp));
      int c=m>1?o[2]:n+1;
      for(int i=o[1];i<c;++i)
        dp[i]=val[i];
      for(int i=2;i<=m;++i)
        for(int j=i<m?o[i+1]-1:n;j>=o[i];--j)
          for(int k=o[i-1];k<o[i];++k)
            dp[j]=max(dp[j],dp[k]+val[j-k]);
       printf("%d\n",(int)(floor(dp[n]*1e6)));
     }
    return 0;
}
View Code

 

HDU5653 Bomber Man wants to bomb an Array 简单DP

标签:

原文地址:http://www.cnblogs.com/shuguangzw/p/5324511.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!