【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