[UVA 11400],dp

题意:现在你要设计一个电力系统,需要用到n种灯泡,每一种灯泡都有它的4个值,电压,电源费用(对于同一种灯泡,只需一个电源),每一个灯泡的费用,该种灯泡必须有的灯泡数量,本来你是想每种灯泡都用对应的电源,既是n个电源,但公司为了省钱,想将一些种类灯泡换成另一种灯泡,让他们公用一个电源,但为了保证场地灯泡足够亮,电压小的可以换成电压大的,电压大的不可以换成电压小的,例如有a,b两种灯泡,电压分别是va,vb,va

分析

线性数据结构上1动态规划
结合贪心思想:

  1. 每个灯要么不换要么全换,因为如果只换一部分还要给两份电源的费用(想到这里很重要)。这次是看书上分析得到的。
  2. dp方程的表示含义:为什么要表示为这种含义?联系dp的两个特性,最优子结构性。那么在每个部分都是最优解,假设已经得到最优解,然后再加一些元素,如何无后效性的得到加长部分的最优解呢?思考一会再看下去。
  3. 基本思想:从极小的子结果得到最优解(很易得),然后用已得的最优解,去比较加上另一部分后的解哪个更优。
  4. 如何验证最优子结构性?首先分析题目的要求:要给每个灯接一个电源,只能往电压高处接,所以要得到整体的最优解,必须要得到部分的最优解,得到接好i-1个灯的最优解,才好比较 i 的最优解。而 i 的最优解不会影响到i-1的最优解。
  5. 控制dp的转移方向:不能往电压低的方向接,而不回头(无后效性),所以要 把电压从小到大排序。
  6. 而初始状态f [ 0 ] = 0,也没有代表什么意义,只不过好转移状态。 在dp的一开始要用到f[0]与f[1]比较,要取min所以其他的 f 初始化为正无穷。
  7. 大致得到dp思路:含义:f[i],1—i的最优解。假设f[ j ]是最优解,让他与 j-i全接到i上比较。如果更优 ,那么,加长后f[j]就变化了。

code

不给全部的,自己补全剩下的。

 f[0]=0;
    sort(a+1, a+1+n, cmp);
    for(int i = 1;i <= n; i++)
    sum[i] = sum[i-1] + a[i].l;
    for(int i = 1; i <= n; i++)//扩展部分
    {    //每一层的扩展 f[ i ] 都是无穷大,所以 f[ i ] 一开始会继承到 j 为止的最优解
         //然后看 j+1 到i全部接到a[i],和原本最优解,哪个更优。
         //在j循环的f[i]并非最优解,而是把本层的结果暂存在f[i]。
        for(int j = 1; j <= i; j++)//子部分
        f[i] = min(f[i] , ( sum[i] - sum[j-1] ) * a[i].k + a[i].c + f[j-1] );

    }
    cout<< f[n] <<endl;

猜你喜欢

转载自blog.csdn.net/k42946/article/details/81122972