HDU5653 Bomber Man wants to bomb an Array 简单DP

题意: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;
}

时间: 2024-08-06 03:39:37

HDU5653 Bomber Man wants to bomb an Array 简单DP的相关文章

【HDOJ 5653】 Bomber Man wants to bomb an Array.(DP)

[HDOJ 5653] 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): 389    Accepted Submission(s): 117 Problem Description Give

HDU 5653 Bomber Man wants to bomb an Array. DP

Bomber Man wants to bomb an Array. 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 wh

HDU5280 Senior&#39;s Array(简单DP)

题目链接:传送门 题意: 给定一个长度为n的序列,和一个修改的值p,必须从原序列中选一个位置修改成p, 求修改后的区间和的最大值. 分析: 枚举位置+最大区间和.复杂度O(n^2); 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; typedef long long LL; const int ma

C#:System.Array简单使用

1.C# 中的数组 1.1 定义数组: 1.1.1 定义不初始化:数据类型[] 数组名称= new 数据类型[元素个数];    1.1.2 定义并初始化:数据类型[] 数组名称= new 数据类型[]{array1,array2}; 1.2 System.Array 类    C#中提供了一个现成的名为System.Array的类,可以通过这个类提供的属性和方法对数组执行大多数操作. 1.2.1 System.Array 对象创建:Array类是一个抽象类,不能使用如下方式创建        

C. Ayoub and Lost Array cf dp

C. Ayoub and Lost Array time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Ayoub had an array aa of integers of size nn and this array had two interesting properties: All the integers in the a

84. Largest Rectangle in Histogram (Array; Stack, DP)

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]. The largest

【Coder Force】#360B - Levko and Array(DP 二分枚举)

题目大题:CF上的题目还是比较容易读懂的.这道题的意思嘛,他是说,有一个不超过2000个数的数组,每一个数与后面的数的绝对值称为value,那么所有当中最大的value就是整个数组的value,现在你有k次变换,每一次可以将其中的一个数变为任何一个使得数组价值最小的数. 假如题目的价值是所有的之和,也可以用这道题的方法. 思路: dp[i]表示的是到i这个位置,使得数组符合条件的最少变换次数. 这个符合条件就奇妙了,这个符合条件是由你定的,最终的符合条件就是答案. 简单来说:你举例一个答案,放进

BestCoder Round #77 (div.2)(hdu5650,hdu5651(逆元),hdu5652(二分),hdu5653(dp))

so easy 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5650 解题思路: 中文题目: 问题描述 已知一个包含 nn 个元素的正整数集合 SS,设 f(S)f(S) 为集合 SS 中所有元素的异或(XOR)的结果. 如:S = \{1, 2, 3\}S={1,2,3}, 则 f(S) = 0f(S)=0. 给出集合 SS,你需要计算 将所有 f(s)f(s) 进行异或后的值, 这里 s \subseteq Ss?S. 输入描述 多组测试数

Codeforce 371A K-Periodic Array(模拟)

题目链接 K-Periodic Array 简单题,直接模拟即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 7 const int N = 100000 + 10; 8 9 int a[N]; 10 int n, k; 11