首页 > 其他 > 详细

HDU5653 Bomber Man wants to bomb an Array 简单DP

时间:2016-03-27 01:18:36      阅读:295      评论: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
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!