【区间DP】戳气球 题解
戳气球
有 n 个气球,编号为 000 到 n−1n−1n−1,每个气球上标有一个数字 aia_iai。现在要求你戳破所有气球。当你戳破气球 iii 时,你可以获得 该气球本身乘相邻的两个气球上的数字个硬币。
你的任务是找到戳破所有气球所能获得硬币的最大数量。
注意:
- 当一个气球被戳破时,其左侧气球的右侧被认为没有气球,右侧气球的左侧被认为没有气球。
- 当一个气球左侧与右侧均没有气球时,其无法被戳破。
- 戳破气球的顺序不同,获得的硬币数也可能不同。
输入格式
输入包含两行:
第一行:一个整数 nnn,表示气球的数量。
第二行:nnn 个整数,其中第 iii 个数 表示编号为 iii 的气球上的数字。
输出格式
输出一个整数,表示戳破所有气球所能获得硬币的最大数量。
输入 / 输出例子 1 输入:
4 3 1 5 8
输出:
55
提示
数据范围 2≤n≤5002 \le n \le 5002≤n≤500,0≤ai≤1000 \le a_i \le 1000≤ai≤100
样例解释:
第一步戳破 888,得 5×8=405× 8 =405×8=40 个分
第二步戳破 111,得 3×1×5=153×1×5 =153×1×5=15 分
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=500+7;
int n,a[N],dp[N][N];
void solve(){cin>>n;a[0]=1,a[n+1]=1;//赋初值,不然乘0等于0for(int i=1;i<=n;i++){cin>>a[i];}for(int s=2;s<=n;s++){for(int l=1;l+s-1<=n;l++){int r=l+s-1;for(int k=l;k<=r;k++){int x=a[k];if(k>l) x*=a[k-1];//为了不超过区间if(k<r) x*=a[k+1];dp[l][r]=max(dp[l][r],dp[l][k-1]+dp[k+1][r]+x);}}}cout<<dp[1][n];
}
signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);int T=1;while(T--){solve();}return 0;
}