• 石子合并


    首先看题:

    有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

    设状态f(i,j),1<=i<=j<=n表示从第i堆到第j堆所需要的最小代价。

    找规律 a[i,j]表示i到j堆的数量

    f(1,1)=w[1]

    f(1,2)=w[1]+w[2]=f(1,1)+f(2,2)       //没有+a[1,2],因为这只是合并了2->1个堆,自己画图

    f(2,2)=w[2]

    f(1,3)=min{f(1,1)+f(2,3),f(1,2)+f(3,3), f(1,3)+f(3,3)}+a[1,3] //想想,为什么要加上。画图

    f(2,3)=w[2]+w[3]=f(2,2)+f(3,3)

    f(3,3)=w[3]

    f(1,4)=min{f(1,1)+f(2,4), f(1,2)+f(3,4), f(1,3)+f(3,4),f(1,4)+f(4,4)}

    .......

    统一一下f(i,i)即将它初始化为0,不然值就会多加了一倍TAT。然后可以发现:

    f(i,j)=min{f(i,j), f(i,k)+f(k+1,j)}+a[i,j]  (i<=k<=j-1, 1<=i<=j<=n)

    a[i,j]可以用dp在O(n)的时间内得到,设一个一维数组

    sum[i]=sum[i-1]+w[i] (2<=i<=n)

    sum[1]=a[1]

    a[i,j]就相当于sum[j]-sum[i-1]

    这时候方程就是

    f(i,j)=min{f(i,j), f(i,k)+f(k+1,j)}+sum[j]-sum[i-1](,i<=k<=j-1, 1<=i<=j<=n)

    咱们来画图。。(矩阵)

    用一个二维数组F[i][j]表示f(i,j)。在矩阵上行的表示i,列表是j(为了方便)

    如图:

    由此可知道顺序。。则递推程序如下。(我不要下标0了,从1开始,方便,而且-1不会越界)

    for(j = 1; j <= n; j++)
    	for(i = j; i > 0; i--)
    		for(k = i; k < j; k++)
    			f[i][j] = min(f[i][j], f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);

    j可以看成图中的i, i则是j。f[i][j]即从i堆到j堆所需最小的代价。

    初始化很重要= =。 非常,非常= =。。。。要将f[i][i]初始化为0,其中1<=i<=n

    并且将f[i][j]都要初始化为INF(一个很大很大的值),否则会出错。

    因为是从下标1开始,下标0的自然要初始化为0,如果声明的是全局变量一般都会清0的,这一步可以省略。

    放上完整代码= =。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 120;
    const int INF = 1000000000;
    int w[MAXN], n, f[MAXN][MAXN], sum[MAXN];
    int i, j, k;
    
    int main()
    {
    	cin >> n;
    	for(i = 1; i <= n; i++) for(j = 1; j <= n; j++) f[i][j] = INF;
    	for(i = 1; i <= n; i++) {cin >> w[i]; f[i][i] = 0; sum[i] += sum[i-1]+w[i];}
    	for(j = 1; j <= n; j++)
            for(i = j; i > 0; i--)
            	for(k = i; k < j; k++)
            		f[i][j] = min(f[i][j], f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
    	cout << f[1][n] << endl;
    	return 0;
    }
  • 相关阅读:
    RTC是DS1339,驱动采用的是rtc-ds1307.c
    hi3515 rtc驱动(ds1307/1339)驱动和示例
    qt5.4.1的imx6编译
    Python实现ID3(信息增益)
    Python实现nb(朴素贝叶斯)
    Python实现kNN(k邻近算法)
    Android实现地图服务
    Android实现传感器应用及位置服务
    Android实现KSOAP2访问WebService
    Android实现网络访问
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3521796.html
Copyright © 2020-2023  润新知