n n n个士兵在不同的位置,自己每秒可以往左移或者往右移动1格,并且干掉改格所在的士兵。
有 m m m秒,第 k k k秒干掉士兵可以获得 m − k m-k m−k的价值,求最大价值之和。
离散化先
然后我们干掉的士兵一定一个线段,所以我们设
f i , j , t , 0 / 1 f_{i,j,t,0/1} fi,j,t,0/1表示第 t s t\ s t s已经干掉了 i ∼ j i\sim j i∼j的士兵,然后在最左边还是在最右边
但是我们发现 t t t的范围十分的大,我们考虑转换。
假设我们总共要干掉 k k k个人,如果还剩下 z z z个人没被干掉,那么没移动一步就会消耗 k k k点价值。
那么我们就可以列出新的方程 f i , j , k , 0 / 1 f_{i,j,k,0/1} fi,j,k,0/1表示总共要干掉 i ∼ j i\sim j i∼j的士兵,然后在最左边还是在最右边。
然后因为全程 k k k那个维度不会有任何交接我们可以不用记录,但是还是要枚举 k k k。
最终状态:
设 f i , j , 0 / 1 f_{i,j,0/1} fi,j,0/1表示总共干掉 k k k个人,已经干掉了 i ∼ j i\sim j i∼j的人,在最左边还是在最右边,
那么我们可以列出动态转移方程
f i , j , 0 = m a x { f i + 1 , j , 0 + m − d i s t ( i , i + 1 ) ∗ ( k − j + i ) , f i + 1 , j , 1 + m − d i s t ( i , j ) ∗ ( k − j + i ) } f_{i,j,0}=max\{f_{i+1,j,0}+m-dist(i,i+1)*(k-j+i),f_{i+1,j,1}+m-dist(i,j)*(k-j+i)\} fi,j,0=max{fi+1,j,0+m−dist(i,i+1)∗(k−j+i),fi+1,j,1+m−dist(i,j)∗(k−j+i)}
f i , j , 1 = m a x { f i , j − 1 , 1 + m − d i s t ( j , j − 1 ) ∗ ( k − j + i ) , f i , j − 1 , 0 + m − d i s t ( i , j ) ∗ ( k − j + i ) } f_{i,j,1}=max\{f_{i,j-1,1}+m-dist(j,j-1)*(k-j+i),f_{i,j-1,0}+m-dist(i,j)*(k-j+i)\} fi,j,1=max{fi,j−1,1+m−dist(j,j−1)∗(k−j+i),fi,j−1,0+m−dist(i,j)∗(k−j+i)}
然后答案就是 f l , r ( r − l + 1 = k , m i d ∈ [ l . . r ] ) f_{l,r}(r-l+1=k,mid\in [l..r]) fl,r(r−l+1=k,mid∈[l..r])
#pragma GCC optimize(2)
#include
#include
#include
#include
using namespace std;
const int N=320;
int n,m,a[N],ans,K;
int f[N][N][2];
inline int read() {
int x=0,f=1; char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
a[i]=read();
a[++n]=0;
sort(a+1,a+1+n);
int mid=lower_bound(a+1,a+1+n,0)-a;
for(K=1;K<=n;K++){
memset(f,0xcf,sizeof(f));
f[mid][mid][0]=f[mid][mid][1]=0;
for(int i=mid;i>0;i--)
for(int j=mid;j<=n;j++){
if(i==j) continue;
if(j-i+1>K) break;
f[i][j][0]=max(f[i+1][j][0]+m-(a[i+1]-a[i])*(K-j+i),f[i+1][j][1]+m-(a[j]-a[i])*(K-j+i));
f[i][j][1]=max(f[i][j-1][1]+m-(a[j]-a[j-1])*(K-j+i),f[i][j-1][0]+m-(a[j]-a[i])*(K-j+i));
if(j-i+1==K)
ans=max(ans,max(f[i][j][0],f[i][j][1]));
}
}
printf("%d",ans);
}