今天这题好难受
好难受好难受。。。
区间型和之前的两种还是有一定差距的。
就40行代码,但是真的写起来还是挺别扭的。
区间型动态规划第一题:
题目:
有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。
输入描述:
第一行一个整数n(n<=100)
第二行n个整数w1,w2...wn (wi <= 100)
输出描述:
一个整数表示最小合并代价
样例输入:
4
4 1 1 4
样例输出:
18
我的答案:
好难受哦我的妈呀。。。
这题这个表可不好填。。
没啥话说了,不好形容,说不清。。。
几点Kevin的教导:
1.一般来说问题让你求啥,f就代表啥
2.之所以说sum可以一维,就是为了减少存储空间,然后之所以提前计算sum就是为了预处理,防止在动态规划的时候多次重复计算,浪费时间
3.对于数组初始化:
假如写在main的话
sum[5]={0}全0
sum[5]={1}第一个为1,其他为0
假如不初始化,就不一定是什么了
全局变量的话不初始化也是0
用Devc++写的。
4.开数组的时候大气一点,比如100个数据,你可以开200以上,这样在满足要求的空间下数组尽量开大一点。算法题目一般空间复杂度比较大,假如在公司开发的话,能少就少。OJ不要钱,不用心疼服务器。。。OJ应该会默认给你最大空间,用不用的都在那放着
懒得总结了,草纸直接贴上来。注意是从对角线开始斜着填。(草纸上的表是最开始的错误版,whatever,大体意思是一样的)
转移方程代码里有。
注释也很详细的
代码:
#include <iostream>
using namespace std;
int w[101];
int f[101][101]; //f[i][j] 从第i堆到第j堆的时候总代价
int sum[101]; //0-i的石子总和
//状态转移方程: f[i][j]=min(f[i][k]+f[k+1][j]+res(i,k)+res(k+1,j)); i<=k<j
int res(int i,int j) //i-j石子总和
{
int res=0;
res=sum[j]-sum[i-1];
return res;
}
int main()
{
int n=0,i=0,j=0,k=0;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>w[i]; //输入
sum[i]=sum[i-1]+w[i];
}
for(i=1;i<n;i++) //端点差值
for(j=1;j<=n-i;j++) //左端点
{
k=j;
f[j][j+i]=100000000; //初始化
while(k<j+i)
{
f[j][j+i]=min(f[j][j+i],f[j][k]+f[k+1][j+i]+res(j,k)+res(k+1,j+i));
k++;
}
}
cout<<f[1][n];
return 0;
}
加油~