码迷,mamicode.com
首页 > 编程语言 > 详细

区间型动态规划的记忆化搜索实现与环形动态规划的循环数组实现

时间:2018-07-14 11:58:08      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:方式   string   ==   out   min   使用   stream   clu   ace   

区间型动态规划的典型例题是石子归并,同时使用记忆化搜索实现区间动归是一种比较容易实现的方式,避免了循环数组实现的时候一些边界的判断

n堆石子排列成一条线,我们可以将相邻的两堆石子进行合并,合并之后需要消耗的代价为这两堆石子的质量之和,问最小的合并代价

状态转移方程很容易给出:

f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[i][j])

因为要计算区间和,考虑前缀和进行预处理

然后我们给出用记忆化搜索形式实现的代码,这里的记忆化搜索形式可以作为后续问题的一个模板

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int INF=0x7fffffff;
 6 const int maxn=105;
 7 int n;
 8 int w[maxn];
 9 int g[maxn];  //前缀和 
10 int f[maxn][maxn];
11 int dfs(int l,int r)
12 {
13     if(l==r) return 0;
14     if(f[l][r]!=INF)
15         return f[l][r];
16     int tmp=INF;
17     for(int i=l;i<r;i++)
18         tmp=min(tmp,dfs(l,i)+dfs(i+1,r)+g[r]-g[l-1]);
19     if(tmp<f[l][r])
20     f[l][r]=tmp;
21     return f[l][r];
22 }
23 int main()
24 {
25     cin>>n;
26     for(int i=1;i<=n;i++)
27     {
28         cin>>w[i];
29         g[i]=g[i-1]+w[i];
30     }
31     memset(f,127,sizeof(f));
32     cout<<dfs(1,n)<<endl;
33     return 0;
34 }

这个问题还是比较显然的,我们考虑另一个问题,那就是环形动态规划

其实环形动态规划也是区间型,只不过区间首尾相接

此时使用记忆化搜索实现,其实是不容易的

典型例题是能量项链

先给出状态转移方程:

f[i][j]=max(f[i][j],f[i][k]+f[k][j]+a[i]*a[j]*a[k])

由于每一种区间问题的价值计算方式不一样,可能采用不同的优化形式,本题直接计算即可

然后我们给出使用循环数组方式实现的一个固定的格式,所有的区间型动态规划都可以采取这样的形式来实现

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int maxn=1005;
 5 int n;
 6 int a[maxn];
 7 long long ans=0;
 8 int f[maxn][maxn];
 9 void dp()
10 {
11     for(int l=2;l<=n;l++)  //区间长度 
12     for(int i=1;i<=n*2-l+1;i++)  //区间起点 
13     {
14         int j=i+l;  //区间终点 
15         for(int k=i+1;k<=j-1;k++)  //区间中任意点 
16             f[i][j]=max(f[i][j],f[i][k]+f[k][j]+a[i]*a[j]*a[k]);
17     }
18     for(int i=1;i<=n;i++)
19     if(ans<f[i][i+n])
20         ans=f[i][i+n];
21 }
22 int main()
23 {
24     cin>>n;
25     for(int i=1;i<=n;i++)
26     {
27         cin>>a[i];
28         a[n+i]=a[i];
29     }
30     dp();
31     cout<<ans;
32     return 0;
33 }

分别枚举区间的长度,区间的起点和区间中的任意点就好了

区间型动态规划的记忆化搜索实现与环形动态规划的循环数组实现

标签:方式   string   ==   out   min   使用   stream   clu   ace   

原文地址:https://www.cnblogs.com/aininot260/p/9308791.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!