题目连接:https://ac.nowcoder.com/acm/contest/8688/E
CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/109407374
As we all know, in the ACM ICPC held in 2017, the organizer of * University presented a box of walnuts to each coach. Our coach is happy to share with the team members except Mr.Watermelon. He is going to test Mr.Watermelon with a game when Mr.Watermelon want to eat some walnuts.
He put some walnuts in a row and let Mr.Watermelon pick one of them. And this walnut is not the first or last in the queue. The price Mr.Watermelon need to pay is : the walnut, the walnut in front of the walnut, and the walnut behind the walnut , the square of the sum of the size of these three walnuts.
For example, now there is a row of walnuts in front of Mr.Watermelon. Their size is: 3 1 50 20 15. If this time Mr.Watermelon picked the third walnut. He needs to pay (1 + 50 + 20) ∗ (1 + 50 + 20) = 5041.
After a walnut is taken away, it will leave the queue. Then Mr.Watermelon picks a walnut again until only two walnuts remain in the queue.
Mr.Watermelon wants to know what the minimum price he will pay when he takes walnuts until there are only two walnuts in the queue. But he needs more time to spend with his girlfriend. So he ask you to help him calculate this problem.
输入描述:
Input contains multiple test cases.The first line of each test case contains a integer n(3 ≤ n ≤ 100), the number of walnuts at the beginning. The second line contains n positive integers separated by spaces, representing the size of each walnut. Each positive integer does not exceed 1,000.
For 50% of the testcases, n ≤ 50.
For 90% of the testcases, n ≤ 90.
For 100% of the testcases, n ≤ 100.
The number of the testcases does not exceed 1000.
输出描述:
For each test case, print a integer–the minimum price Mr.Watermelon will pay.
示例1
输入
5
3 1 50 20 15
输出
6698
题目大意:给你n件商品,你不能够买第一件和最后一件,而你买第i个商品的代价是\((a_i+a_{i+1}+a_{i-1})^2\),问最后买光所有商品的最小代价是多少
emmm,本来可以一发AC的。。。结果inf开小了QAQ。一看这玩意儿就知道是个区间DP,那么于是三连for上头,枚举长度,枚举起点,枚举终点,由于第一件和最后一件不能买,所以有:
for (int len=2; len<=n-2; len++){//由于2个买不了,所以长度只有n-2
for (int st=2; st+len-1<=n-1; st++){//对2-n-1进行区间DP
int ed=st+len-1;
for (int k=st; k<=ed; k++){
.....
}
}
}
那么DP的转移方程怎么写呢,其实之前博客里面有一题杀狼的题目也是相同的道理https://www.cnblogs.com/lonely-wind-/p/13264259.html
我们枚举中间的保留点,那么就可以得到其方程:
\(dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+(a[k]+a[i-1]+a[j+1])^2)\)
#include <bits/stdc++.h>
using namespace std;
const int mac=120;
const int inf=5e8+10;
int a[mac],dp[mac][mac];
int pw(int x){return x*x;}
int main(int argc, char const *argv[])
{
int n;
while (~scanf ("%d",&n)){
for (int i=1; i<=n; i++)
scanf ("%d",&a[i]);
for (int i=1; i<=n; i++)
for (int j=i; j<=n; j++)
dp[i][j]=inf;
for (int i=2; i<n; i++) dp[i][i]=pw(a[i]+a[i-1]+a[i+1]);
for (int len=2; len<=n-2; len++){
for (int st=2; st+len-1<=n-1; st++){
int ed=st+len-1;
for (int k=st; k<=ed; k++){
dp[st][ed]=min(dp[st][ed],dp[st][k-1]+dp[k+1][ed]+pw(a[k]+a[st-1]+a[ed+1]));
}
}
}
printf ("%d\n",dp[2][n-1]);
}
return 0;
}