首页 > 技术文章 > 洛谷p1880石子合并

LQS-blog 2022-02-15 21:51 原文

题目链接:https://www.luogu.com.cn/problem/P1880

正宗的石子合并,当然,这个题不同于弱化版的是他是环形石子合并,因为题目说在一个圆形操场的四周摆放 N堆石子,思路依旧是区间内进行动态规划,但是细节上要注意了,为了满足题目要求,需要将数组扩充为2*n以满足环形,这样相比于取模运算更容易理解一些。

大体思路:

大体思路同石子合并弱化版一致,但是初始化时候要扩充两倍。

具体操作参考代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[300];
 4 int dp[300][300];//从i到j所付出的最小价值 
 5 int up[300][300];//从i到j所付出的最大价值 
 6 int sum[300];//从区间i到区间j的石子堆和 
 7 int n;
 8 void minval()
 9 {
10     for(int len=1;len<2*n;len++)//区间长度,i--j的长度,但是要扩充到2*n 
11     {
12         for(int i=1;i<=2*n-len;i++)//起点i同样要扩充 
13         {
14             int j=i+len;//终点 
15             dp[i][j]=INT_MAX;//最小标兵初始化最大 
16             up[i][j]=-1;//最大标兵初始化最小 
17             for(int k=i;k<j;k++)//区间i-k-j
18             {
19                 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);//详情请看上一篇博文 
20                 up[i][j]=max(up[i][j],up[i][k]+up[k+1][j]+sum[j]-sum[i-1]);//详情请看上一篇博文 
21             }
22         }
23     }
24 }
25 int main()
26 {
27     int ans=INT_MAX,cnt=0;
28     ios::sync_with_stdio(false);
29     cin>>n;
30     for(int i=1;i<=n;i++)
31     cin>>a[i];
32     for(int i=1;i<=2*n;i++)//扩充2倍 
33     {
34         a[i+n]=a[i];//环形赋值 
35         sum[i]=sum[i-1]+a[i];
36         dp[i][i]=0;
37         up[i][i]=0;
38     }
39     minval();
40     for(int i=1;i<=n;i++)
41     {
42         ans=min(ans,dp[i][i+n-1]);//区间内最小的 
43         cnt=max(cnt,up[i][i+n-1]);//区间内最大的 
44     }
45     cout<<ans<<endl<<cnt;
46     return 0;
47 }

 

推荐阅读