题目大意:
有n个数,每次操作选择移除一个数,代价为这个数左边的数乘以这个数再乘以这个数右边的数,不可以移除第一个数和最后一个数,问最小代价。
题解:定义状态dp[l][r]区间l,r需要的最小代价,状态转移 dp[l][r]=min(dp[l][i]+dp[i][r]+arr[i]*arr[l]*arr[r]),就是枚举区间l,r进行转移。
注:我是这样枚举的dp[l][i]+dp[i+1][r]+min(arr[l]*arr[i]*arr[i+1]+arr[i+1]*arr[r]*arr[l],arr[i]*arr[i+1]*arr[r]+arr[l]*arr[r]*arr[i]),感觉没错啊,但是一直wa......
code:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; typedef long long ll; const ll N=100+7; ll dp[N][N]; ll arr[N]; int main(){ ll n; while(cin>>n){ for(ll i=1;i<=n;i++) cin>>arr[i]; memset(dp,0,sizeof dp); for(ll i=2;i<=n-1;i++) dp[i-1][i+1]=arr[i]*arr[i-1]*arr[i+1]; for(ll len=4;len<=n;len++){ for(ll l=1,r=len;r<=n;r++,l++){ ll cnt=1000000000+7; for(int i=l+1;i<=r-1;i++){ cnt=min(cnt,dp[l][i]+dp[i][r]+arr[i]*arr[l]*arr[r]); } dp[l][r]=cnt; } } cout<<dp[1][n]<<endl; } return 0; }