题意:给一个长度为 N 的一维格子和一些炸弹的位置,请你计算 “最大总破坏指数”。
每个炸弹都有向左和向右的破坏力,如果一个炸弹向左和向右的破坏力分别为 L 和 R,
那么该炸弹将炸毁 L + R + 1个格子(左边L个,炸弹所在格子,右边R个)。
破坏指数的计算方式为:所有炸弹炸毁的格子数的乘积。假设第 i 个炸弹炸毁了 X_i个格子,
那么总破坏指数就是 X_1 * X_2 * .... X_m
现在告诉你每个炸弹的位置,你需要计算 最大的总破坏指数,注意:每个格子最多只允许被炸一次。(n<=2000)
思路:dp,dp[i][j]表示到了第i个位置,该位置选择的R的位置为j,那么状态转移方程为dp[i][j]=max(dp[i-1][k]+log2(k-j)),k表示第i-1个位置选择的R的位置。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2001;
double dp[2][maxn];
int a[maxn];
int main(){
int _,n,m;
scanf("%d",&_);
while(_--){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d",&a[i]),a[i]++;
sort(a+1,a+m+1);
a[0]=0,a[m+1]=n+1;
memset(dp,0,sizeof(dp));
int flag=0;
for(int i=1;i<=m;i++){
for(int j=a[i-1];j<=a[i]-1;j++)//上一个的右边
for(int k=a[i];k<=a[i+1]-1;k++)//这一个的右边
dp[flag^1][k]=max(dp[flag^1][k],dp[flag][j]+log(k-j)/log(2));
flag^=1;
}
printf("%lld\n",(long long)floor(dp[flag][n]*1000000));
}
return 0;
}