3499. 序列最大收益
题目链接https://www.acwing.com/problem/content/3502/
题目:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,k,m;
int w[210][210];
int a[210],f[210][210];//f[i][j]的定义是在第i个数之前选j个数删去求到的最大和
int main(){
cin>>n>>k>>m;
for(int i=1;i<=m;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&w[i][j]);
memset(f,-0x3f,sizeof f);
f[1][0]=0;//如果就一个数,那么就为0
for(int i=2;i<=m;i++){//i从第2~m
for(int j=0;j<=k;j++){
for(int z=1;z<i;z++){//f[i][j],现在就是遍历一下i的左边最近的那个数的可能值
if(j>=i-z-1)//但到左边最近的那个数z,中间要删去的步数为i-z-1;
f[i][j]=max(f[i][j],f[z][j-(i-z-1)]+w[a[z]][a[i]]);
}
}
}
int res=0;
for(int i=0;i<=k;i++)//因为在m个数之前删除不一样的i,得到的答案是不一样的,但都是删除i个数里面的最优值,
if(f[m][i]>res) res=f[m][i];//故都要比较一下大小
cout<<res;
return 0;
}