标签:
【HDOJ 5653】 Bomber Man wants to bomb an Array.(DP)
2 10 2 0 9 10 3 0 4 8
4643856 5169925
题目大意:有n个块。在其中m块上装有炸药。
要求引爆这些炸药。每个炸药可以由你给定一个左右引爆边界[L,R]表示向左L个块 向右R个块会被摧毁,即爆炸威力为L+R+1(本身所在的块也被摧毁)
设第i个炸药的爆炸威力为Xi
那么总的爆炸威力为X1*X2*X3*X4*...*Xm
问floor(1000000 * log2(Maximum Total Impact)) floor为向下取整函数 Maximum Total Impact为最大爆炸威力和
求log2就是因为成起来太大了。
利用log的性质,可知log(m,(a*b) ) = log(m,a)+log(m,b)
这样用dp[i]表示炸到第i个块可以得到的最大爆炸威力的log
这样可以枚举所有的炸药,对于每个炸药枚举爆炸范围[L,R] 枚举到左右的炸药即可
这样转移方程就是dp[R] = max(dp[R],dp[L-1]+log(R-L+1)/log2)
代码如下:
#include <iostream> #include <cmath> #include <vector> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <stack> #include <list> #include <algorithm> #include <map> #include <set> #define LL long long #define Pr pair<int,int> #define fread() freopen("in.in","r",stdin) #define fwrite() freopen("out.out","w",stdout) using namespace std; const int INF = 0x3f3f3f3f; const int msz = 10000; const int mod = 1e9+7; const double eps = 1e-8; double dp[2333]; int boom[2333]; int main() { //fread(); //fwrite(); int t,n,m; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); boom[0] = 0; boom[m+1] = n+1; for(int i = 1; i <= m; ++i) { scanf("%d",&boom[i]); boom[i]++; } sort(boom+1,boom+m+1); memset(dp,0,sizeof(dp)); for(int i = 1; i <= m; ++i) { for(int l = boom[i-1]+1; l <= boom[i]; ++l) { for(int r = boom[i+1]-1; r >= boom[i]; --r) { dp[r] = max(dp[r],dp[l-1]+log((r-l+1)*1.0)/log(2.0)); } } } LL ans = floor(1e6*dp[n]); printf("%lld\n",ans); } return 0; }
【HDOJ 5653】 Bomber Man wants to bomb an Array.(DP)
标签:
原文地址:http://blog.csdn.net/challengerrumble/article/details/51000900