[codevs1048]石子归并&[codevs2102][洛谷P1880]石子归并加强版
codevs1048:
题目大意:有n堆石子排成一列,每次可合并相邻两堆,代价为两堆的重量之和,求把他们合并成一堆的最小代价。
解题思路:经典区间dp。设$f[i][j]$表示合并i~j的石子需要的最小代价。则有$f[i][j]=min(f[i][k]+f[k+1][j]+\sum\limits _{l=i}^{j}a[l])$,时间复杂度$O(n^3)$。
C++ Code:
#include<cstdio>
#include<cstring>
using namespace std;
int n,a[102],f[102][102],s[102];
int main(){
scanf("%d",&n);
memset(f,0x3f,sizeof f);
for(int i=1;i<=n;++i)scanf("%d",&a[i]),s[i]=s[i-1]+a[i],f[i][i]=0;
for(int i=n;i;--i)
for(int j=i+1;j<=n;++j)
for(int k=i;k<j;++k)
if(f[i][j]>f[i][k]+f[k+1][j]+s[j]-s[i-1])f[i][j]=f[i][k]+f[k+1][j]+s[j]-s[i-1];
printf("%d\n",f[1][n]);
return 0;
}
注意代码第9行,为什么i要倒着循环?举个栗子,如果要求f[1][10],就有f[1][10]=min(f[1][10],f[1][5]+f[6][10]+sum[1][10]),但是i才循环到1,就需要f[6][10]的结果,于是导致答案错误。而倒着循环,就可保证i+1~n的所有数据都已求完,就不会导致答案错误了。
codevs2102&&洛谷P1880:
题目大意:有n堆石子摆成环状,每次可合并相邻两堆,代价为两堆的重量之和,求把他们合并成一堆的最小代价和最大代价。
解题思路:本题除了是个环以外,和上题没什么区别。我们可以用化环为链的方法,具体的实现就是将这个环的单圈复制一遍,然后做n次上述dp即可。求最大价值就是把状态转移方程里的$min$改成$max$即可。时间复杂度$O(n^4)$,但代码运行量应该是不到这个极限的。
C++ Code:
#include<cstdio>
#include<cstring>
using namespace std;
int n,a[202],fmax[202][202],fmin[202][202],s[202],Max=0,Min=200000000;
void dp(int h){
for(int i=n;i;--i){
fmax[i+h][i+h]=fmin[i+h][i+h]=0;
for(int j=i+1;j<=n;++j){
fmax[i+h][j+h]=0;
fmin[i+h][j+h]=200000000;
for(int k=i;k<j;++k){
if(fmax[i+h][j+h]<fmax[i+h][k+h]+fmax[k+h+1][j+h]+s[j+h]-s[i+h-1])
fmax[i+h][j+h]=fmax[i+h][k+h]+fmax[k+h+1][j+h]+s[j+h]-s[i+h-1];
if(fmin[i+h][j+h]>fmin[i+h][k+h]+fmin[k+h+1][j+h]+s[j+h]-s[i+h-1])
fmin[i+h][j+h]=fmin[i+h][k+h]+fmin[k+h+1][j+h]+s[j+h]-s[i+h-1];
}
}
}
if(Max<fmax[1+h][n+h])Max=fmax[1+h][n+h];
if(Min>fmin[1+h][n+h])Min=fmin[1+h][n+h];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&a[i]),s[i]=s[i-1]+a[i];
for(int i=n+1;i<2*n;++i)
a[i]=a[i-n],s[i]=s[i-1]+a[i];
for(int i=1;i<=n;++i)
dp(i-1);
printf("%d\n%d\n",Min,Max);
return 0;
}
[codevs1048]石子归并&[codevs2102][洛谷P1880]石子归并加强版的更多相关文章
- 洛谷P1880 石子合并(区间DP)(环形DP)
To 洛谷.1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1 ...
- 经典DP 洛谷p1880 石子合并
https://www.luogu.org/problemnew/show/P1880 题目 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新 ...
- 洛谷P1880 石子合并(环形石子合并 区间DP)
题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1 ...
- 洛谷 P1880 石子合并
题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1 ...
- 洛谷P1880 石子合并
经典水题....... 断环为链长度乘二,求前缀和区间DP. #include <cstdio> #include <cstring> #include <algorit ...
- 洛谷P1880 [NOI1995]石子合并 纪中21日c组T4 2119. 【2016-12-30普及组模拟】环状石子归并
洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石 ...
- codevs 1048/洛谷 1880:石子归并
题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使 ...
- 洛谷 P1880 [NOI1995] 石子合并(区间DP)
传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 这道题是石子合并问题稍微升级版 这道题和经典石子合并问题的不同在于,经典的石子合 ...
- 洛谷 P6031 - CF1278F Cards 加强版(推式子+递推)
洛谷题面传送门 u1s1 这个推式子其实挺套路的吧,可惜有一步没推出来看了题解 \[\begin{aligned} res&=\sum\limits_{i=0}^ni^k\dbinom{n}{ ...
随机推荐
- Unity的SendMessage方法
用法(该对象所有脚本都能收到): gameObject.SendMessage("要执行的方法名"); 通知的另一种实现: gameObject.GetComponent<脚 ...
- u-boot启动代码start.S详解360
(1)定义入口.由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本 ...
- Vue常用的GitHub项目
Vue常用的GitHub项目(Demo案例) 应用实例 https://github.com/pagekit/pa... pagekit-轻量级的CMS建站系统 https://github.com/ ...
- C#WIFI搜索与连接
1.功能搜索WIFI并连接 2.所用工具及资源:VS2012 Managed Wifi API(即:引用ManagedWifi.dll文件地址:http://files.cnblogs.com/fil ...
- ACCESS-入门思维导图
ACCESS-入门思维导图 链接:http://pan.baidu.com/s/1bozYiNt 密码:5tly 如果有错误,请告知我!
- 博客迁移到reetsee.com
正如上一篇博客所言.眼下CSDN的博客已经基本完毕它的使命了.感谢CSDN带给我的全部美好回顾. 如今我想尝试一下自己维护一个博客,所以博客的全部内容都迁移到了reetsee.com. 以后博客更新会 ...
- codevs 3372 选学霸(hash+并查集+多重背包)
先通过并查集处理出来有多少种不同的集合,每一个集合有多少人.一定要不要忘记了与别的没有联系的独立点. 并查集的时候能够通过hash处理出来每一个数目同样的集合的个数. 这样以人数为权值.个数为限制进行 ...
- leetCode 72.Edit Distance (编辑距离) 解题思路和方法
Edit Distance Given two words word1 and word2, find the minimum number of steps required to convert ...
- Maximum Bipartite Matching
算法旨在用尽可能简单的思路解决这个问题.理解算法也应该是一个越看越简单的过程,当你看到算法里的一串概念,或者一大坨代码,第一感觉是复杂,此时最好还是从样例入手.通过一个简单的样例,并编程实现,这个过程 ...
- JS冒泡事件 与 事件捕获
JS冒泡事件 与 事件捕获 案例 <!DOCTYPE html> <html> <head> <title>冒泡事件</title> < ...