AT_agc062_b [AGC062B] Split and Insert 对自己的警告--zhengjun

发布时间 2023-07-10 21:46:29作者: A_zjzj

做题时想出来的东西:

  • 时光倒流

做题时的思维定式:

  • 按照操作顺序,挨个算出拿几个数到最后

  • 没有想到在原序列上进行区间 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;
}