难得AK一次,看看大佬T3题解,发现可以有多种解法
解法一:直接暴力
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3010,INF = 0x3f3f3f3f;
int a[N],b[N];
int n;
int main()
{
scanf("%d", &n);
for(int i=0;i<n;i++)scanf("%d",a+i);
for(int i=0;i<n;i++)scanf("%d",b+i);
int res=0x3f3f3f3f;
for(int i=1;i<n-1;i++)
{
int c=INF,d=INF;
for(int j=0;j<i;j++)if(a[j]<a[i])c=min(c,b[j]);
for(int j=i+1;j<n;j++)if(a[j]>a[i])d=min(d,b[j]);
if(c!=INF&&d!=INF)res=min(res,b[i]+c+d);
}
if(res==0x3f3f3f3f)cout<<-1<<endl;
else cout<<res<<endl;
}
解法二:预处理
多开一个数组用来存对于每个中间的数,满足条件的他的前边数的最小值
然后再去枚举第三个数
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3010;
int a[N],b[N],c[N];
int n;
int main()
{
scanf("%d", &n);
for(int i=0;i<n;i++)scanf("%d",a+i);
for(int i=0;i<n;i++)scanf("%d",b+i);
int res=0x3f3f3f3f;
memset(c,0x3f,sizeof c);
for(int i=0;i<n;i++)
for(int j=0;j<i;j++)
if(a[i]>a[j]&&c[i]>b[j])c[i]=b[j];
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
if(a[j]>a[i])res=min(res,c[i]+b[i]+b[j]);
if(res==0x3f3f3f3f)cout<<-1<<endl;
else cout<<res<<endl;
}
解法三:简单DP写法
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3010;
int f[3][N];
int a[N],b[N];
int n;
int main()
{
scanf("%d", &n);
for(int i=0;i<n;i++)scanf("%d",a+i);
for(int i=0;i<n;i++)scanf("%d",b+i);
memset(f,0x3f,sizeof f);
int res=0x3f3f3f3f;
for(int i=0;i<n;i++)
{
f[0][i]=b[i];
for(int j=0;j<i;j++)
{
if(a[i]>a[j])
{
f[1][i]=min(f[1][i],f[0][j]+b[i]);
f[2][i]=min(f[2][i],f[1][j]+b[i]);
}
res=min(res,f[2][i]);
}
}
if(res==0x3f3f3f3f)cout<<-1<<endl;
else cout<<res<<endl;
}