【HDU5653 BestCoder Round 77 (div1) C】【DP 复杂度计算】Bomber Man wants to bomb an Array n炸弹设置爆炸左右界 最大爆炸力的乘积

来源:互联网 发布:男生接吻生理反应知乎 编辑:程序博客网 时间:2024/04/30 23:33

Bomber Man wants to bomb an Array.

 
 Accepts: 56
 
 Submissions: 225
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
给一个长度为 NN 的一维格子和一些炸弹的位置,请你计算 “最大总破坏指数”。每个炸弹都有向左和向右的破坏力,如果一个炸弹向左和向右的破坏力分别为 LLRR,那么该炸弹将炸毁 L + R + 1L+R+1 个格子(左边LL个,炸弹所在格子,右边RR个)。破坏指数的计算方式为:所有炸弹炸毁的格子数的乘积。假设第 ii 个炸弹炸毁了 X_iXi个格子,那么总破坏指数就是 X_1 * X_2 * .... X_mX1X2....Xm。现在告诉你每个炸弹的位置,你需要计算 最大的总破坏指数,注意:每个格子最多只允许被炸一次。
输入描述
多组测试数据,第一行为一个整数 T(T \leq 11)T(T11)。每组测试数据第一行为两个整数 N, M(1 \leq N \leq 2000, 1\leq M \leq N)N,M(1N2000,1MN),分别表示格子总数和炸弹总数 。第二行是 MM 个互不相同的数表示每个炸弹所在的位置。
输出描述
对于每组测试数据,输出 floor(10^6 * log2(最大破坏指数)) (floor表示向下取整)。
输入样例
210 20 910 30 4 8
输出样例
46438565169925
Hint
Sample 1 :
Sample 2:

#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<ctype.h>#include<math.h>#include<set>#include<map>#include<vector>#include<queue>#include<bitset>#include<algorithm>#include<time.h>using namespace std;void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }const int N = 2020, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;int casenum, casei;int n, m;int a[N];double f[N][N];//f[i][j]表示前i个炸弹爆炸,最右界是j,所对应的最大破坏力double lg[N];int main(){for (int i = 1; i <= 2000; ++i)lg[i] = log(i) / log(2);scanf("%d", &casenum);for (casei = 1; casei <= casenum; ++casei){scanf("%d%d", &m, &n);for (int i = 1; i <= n; ++i)scanf("%d", &a[i]), ++a[i];sort(a + 1, a + n + 1); a[0] = 0; a[n + 1] = m + 1;f[0][0] = 0;for (int i = 1; i <= n; ++i){for (int j = a[i]; j <= a[i + 1] - 1; ++j){f[i][j] = 0;for (int k = a[i - 1] + 1; k <= a[i]; ++k){int len = j - k + 1;gmax(f[i][j], f[i - 1][k - 1] + lg[len]);}}}LL ans = floor(f[n][m] * 1000000);printf("%lld\n", ans);}return 0;}/*【trick&&吐槽】1,炸弹的爆炸范围不能超过别的炸弹2,贪心原则是炸弹的爆炸范围尽可能平均3,DP的话,先枚举后爆炸范围,再枚举前爆炸范围【题意】有m个格子排成一排。其中n个不同的位置有炸弹。每个炸弹可以设置其左右爆炸范围,多个炸弹的炸弹范围不可重叠。一个炸弹的破坏力=其炸坏的格子数问你所有炸弹破坏力的乘积的最大值val,并输出floor(log2(val)*1e6)【类型】DP 复杂度计算【分析】我们枚举炸弹枚举右爆炸范围枚举左爆炸范围就可以更新dp[i][j]=max(dp[i-1][l-1]+log2(r-l+1))答案就是dp[n][m]看似枚举了三重n这个复杂度其实只有n^2【时间复杂度&&优化】O(n^2)*/


0 0
原创粉丝点击