AT_agc062_b [AGC062B] Split and Insert 对自己的警告--zhengjun
做题时想出来的东西:
- 时光倒流
做题时的思维定式:
-
按照操作顺序,挨个算出拿几个数到最后
-
没有想到在原序列上进行区间 dp。
-
反复只想到从小到大划分区间,每个区间计算贡献,具有一定局限性
需要发现,在考虑不同的值的时候,选择哪些操作顺序是独立的
代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e2+10;
const ll INF=1e18;
int n,m,a[N],b[N];
ll f[N][N][N];
void chkmin(ll &x,ll y){
if(x>y)x=y;
}
int main(){
freopen(".in","r",stdin);
//freopen(".out","w",stdout);
cin>>n>>m;
for(int i=m;i>=1;i--)cin>>b[i];
for(int i=1;i<=n;i++)cin>>a[i];
memset(f,0x3f,sizeof f);
for(int i=1;i<=n;i++){
int x=i;
for(int j=1;j<=n;j++)x+=x==a[j];
for(int j=i;j<x;j++)f[1][i][j]=0;
}
for(int i=1;i<=m;i++){
for(int l=1;l<=n;l++)for(int r=l;r<=n;r++){
chkmin(f[i+1][l][r],f[i][l][r]);
for(int k=l;k<r;k++)
chkmin(f[i+1][l][r],f[i][l][k]+f[i][k+1][r]+1ll*(r-k)*b[i]);
}
}
if(f[m+1][1][n]<INF)cout<<f[m+1][1][n];
else cout<<-1;
return 0;
}