给一个长度为 NNN 的一维格子和一些炸弹的位置,请你计算 “最大总破坏指数”。 每个炸弹都有向左和向右的破坏力,如果一个炸弹向左和向右的破坏力分别为 LLL 和 RRR, 那么该炸弹将炸毁 L+R+1L + R + 1L+R+1 个格子(左边LLL个,炸弹所在格子,右边RRR个)。 破坏指数的计算方式为:所有炸弹炸毁的格子数的乘积。假设第 iii 个炸弹炸毁了 XiX_iXi个格子, 那么总破坏指数就是 X1∗X2∗....XmX_1 * X_2 * .... X_mX1∗X2∗....Xm。 现在告诉你每个炸弹的位置,你需要计算 最大的总破坏指数,注意:每个格子最多只允许被炸一次。
输入描述
多组测试数据,第一行为一个整数 T(T≤11)T(T \leq 11)T(T≤11)。 每组测试数据第一行为两个整数 N,M(1≤N≤2000,1≤M≤N)N, M(1 \leq N \leq 2000, 1\leq M \leq N)N,M(1≤N≤2000,1≤M≤N),分别表示格子总数和炸弹总数 。 第二行是 MMM 个互不相同的数表示每个炸弹所在的位置。
输出描述
对于每组测试数据,输出 floor(10^6 * log2(最大破坏指数)) (floor表示向下取整)。
输入样例
2 10 2 0 9 10 3 0 4 8
输出样例
4643856 5169925
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int num[2002];
double dp[2002];
int main()
{
int t,n,m;
double log2=log(2);
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
memset(num,0,sizeof(num));
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d",&num[i]);
}
sort(num,num+m);
num[m]=n;
for(int i=num[0];i<num[1];i++)
{
dp[i]=log(i+1)/log2;
}
for(int i=1;i<m;i++)
{
for(int r=num[i];r<num[i+1];r++)
{
for(int l=num[i-1]+1;l<=num[i];l++)
{
dp[r]=max(dp[r],dp[l-1]+log(r-l+1)/log2);
}
}
}
printf("%d\n",int(floor(1e6*dp[n-1])));
}
return 0;
}
看上去是3个for循环,o(n的三次方)其实第一个和第二个for循环统一起来是从0到m-1,最终的时间复杂度最坏是n的平方;
个人感觉是正常区间dp的单向版(由于点的存在)