大佬 蒟蒻来啦!!
这次还是给大家讲解一下DP
有的人可能会问同样是DP,那么这次有什么不同呢?(注意:这篇不仅仅是题解!!)。其实答案很简单,上一篇那到最长不下降子序列是一道线性动态规划的经典模板题,也就是最简单易懂的动态规划(其实类比单链表和双链表)。那么这次我们来看看区间DP,区间DP,其实就是求一个区间内的最优值从而达到求整体最优的效果。一般这种题目,在设置状态的时候,都可以设f[i][j]为区间i-j的最优值 而f[i][j]的最优值,这有两个小区间合并而来的,为了划分这两个更小的区间,我们则需用用一个循环变量k来枚举,而一般的状态转移方程便是:
f[i][j]=max/min(f[i][j],f[i][k]+f[k][j]+something)
f[i][j]=max/min(f[i][j],f[i][k]+f[k][j]+something)
我们则需要根据这个题目的实际含义进行变通即可.
而区间dp的大致模板是:
for (int len=2;len<=n;len++)
for (int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
for (int k=i;k<=j;k++)
f[i][j]=max/min(f[i][j],f[i][k]+f[k][j]+something)
}
那讲到这里就很自然(一点都不自然)的引入了今天我们要看的一道题,刚才我已经说了最长不下降子序列是线性DP的模板题,那么今天说的这道石子合并就是区间DP的经典模板。下面来讲解一下我们先看这道题的题目描述以及输入输出数据点。(如下)
题目描述
在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入格式
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式
输出共2行,第1行为最小得分,第2行为最大得分.
输入输出样例
输入 #1 复制
4
4 5 9 4
输出 #1 复制
43
54
那么上面就是这道题目的内容,即每次进行合并的时候就是合并一个区间.
我们可以设f[i][j]为合并i-j区间的石子的最优方案即最小花费,假设在我们进行i和j的状态转移的时候必然更小的区间已经求出了最优的方案数,那么我们只需要用k去划分石子数去进行状态转移即可.
因为本来的时间是O(n^3),我们则需要优化时间,采用前缀和的方法,把合并的数量进行计算即可.
我们可以得到状态转移方程:
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+cost[i][j])
表示两堆石子的合并花费加上新的花费得到的结果.
在代码实现上,我们需要注意:len是从2开始的,诸如f[1][1],f[2][2]都是不需要花费价值的,即初始值0;状态转移方程是f[i][k]+f[k+1][j]+cost[i][j]) 而不是f[i][k]+f[k][j]+cost[i][j])合并的是两堆不同的石子而不是一堆,这点需要注意.
代码如下:
#include<cstdio>
#include<iostream>
using namespace std;
int a[210],f1[210][210],f2[210][210];
int main()
{
int n,Max,Min;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[n+i]=a[i];
}
for(int i=1;i<=2*n;i++)
{
a[i]=a[i]+a[i-1];
}
for(int r=2;r<=n;r++)
{
for(int i=1;i<=2*n-r+1;i++)
{
int j=i+r-1;
f1[i][j]=f1[i+1][j]+a[j]-a[i-1];
f2[i][j]=f2[i+1][j]+a[j]-a[i-1];
for(int k=i;k<j;k++)
{
f1[i][j]=max(f1[i][j],f1[i][k]+f1[k+1][j]+a[j]-a[i-1]);
f2[i][j]=min(f2[i][j],f2[i][k]+f2[k+1][j]+a[j]-a[i-1]);
}
}
}
Max=f1[1][n];
Min=f2[1][n];
for(int i=2;i<=n;i++)
{
if(f1[i][i+n-1]>Max) Max=f1[i][i+n-1];
if(f2[i][i+n-1]<Min) Min=f2[i][i+n-1];
}
cout<<Min<<endl<<Max;
return 0;
}
其实这道题就是这么简单!!希望大家都能理解区间DP
(后面还有更多更难的DP!!!!)