此处省略原题描述,又长又臭
第一行一个正整数n(2≤n≤300)第二行为n个用空格分开的正整数,表示1~n区域里每把金钥匙的价值。保证运算过程及结果不超出int范围
第一行的一个数,即获得的最大价值。第二行按照分离阶段从前到后,区域从左向右的顺序,输出发生分离的区域编号,中间用一个空格隔开,若有多种方案,选择分离区域尽量靠左的方案(也可以理解为输出字典序最小的)
7
1 2 3 4 5 6 7
238
1 2 3 4 5 6
按区间长度从小到大枚举所有区间 [ j , i ],再枚举所有决策点 t∈[ j , i−1 ],
dp 方程为:dp[j][t]=max(dp[j][t],(a[t]+a[j])*a[k]+ dp[j][k]+dp[k+1][t]);
然后用广搜思路求出路径:区间最优决策点在dp的时候记录一下就可以,输出可以用队列来实现,和bfs的过程类似。
#include
using namespace std;
#define ll long long
const int N=100010;
int ans,a[1000],dp[1000][1000],n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j+i-1<=n;j++)
{
int t=i+j-1;
for(int k=j;k<t;k++)
{
dp[j][t]=max(dp[j][t],(a[t]+a[j])*a[k]+dp[j][k]+dp[k+1][t]);
}
}
}
cout<<dp[1][n]<<endl;
queue<int>q1,q2;
q1.push(1);
q2.push(n);
while(q1.size())
{
int i=q1.front(),j=q2.front();
q1.pop(),q2.pop();
for(int k=i;k<j;k++)
{
if(dp[i][j]==(a[i]+a[j])*a[k]+dp[i][k]+dp[k+1][j])
{
printf("%d ",k);
q1.push(i),q2.push(k);
q1.push(k+1),q2.push(j);
break;
}
}
}
return 0;
}