CDOJ 1131 男神的礼物 区间dp

男神的礼物

Time Limit: 3000/3000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

Lweb学长是集训队里公认的男神。有一天他要给美美的学姐姐准备礼物。

Lweb学长可是会魔法的哟。为了准备一份礼物,男神要加工n份材料。每一次只能加工相邻的材料。

当男神加工两个魔法值为a,b的材料,男神都要消耗a*b的体力,同时在这个地方合成出魔法值(a+b)%100的材料。

男神为了能节省体力来完成他的礼物。想找聪明的你帮他算一算他所要花费的最小体力。

Input

第一行一个整数T,表示男神所要准备的礼物数。 之后的T组数据各有两行数据,第一行有一个整数n,表示这份礼物的材料数(1<=n<=100)。 接下来一行有n个整数a(0<=a<100),表示这件礼物第i份材料的魔法值。

Output

每组数据一行输出,表示男神制作这份礼物所要的最小体力。

Sample input and output

Sample InputSample Output
2
2
18 19
3
40 60 20
342
2400

Hint

对于样例 2:

先加工材料40和60,得到0的材料,消耗40∗60体力,共消耗2400体力;

再加工材料0和20,得到20的材料,消耗0∗20体力,共消耗2400体力.

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
typedef  long long  ll;
typedef unsigned long long ull;
#define MM(a,b) memset(a,b,sizeof(a));
#define inf 0x7f7f7f7f
#define FOR(i,n) for(int i=1;i<=n;i++)
#define CT continue;
#define PF printf
#define SC scanf
const int mod=1000000007;
const int N=1e3+10;

int dp[105][105],sum[105];
int main()
{
    int cas,n,x;
    scanf("%d",&cas);
    while(cas--)
    {
        MM(dp,inf);MM(sum,0);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            dp[i][i]=0;
            sum[i]=sum[i-1]+x;
        }
        for(int r=2;r<=n;r++)
           for(int l=r-1;l>=1;l--)
             for(int k=l;k<=r-1;k++)
             {
                  int ener=((sum[k]-sum[l-1])%100)*((sum[r]-sum[k])%100);
                  dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+ener);
             }
        printf("%d
",dp[1][n]);
    }
    return 0;
}

  分析:设dp[l][r]为合并区间[l,r]范围材料的体力消耗,先固定l,r然后枚举中间值k(k代表将[l,k]和

[k+1,r]范围内的材料合并,当然前提是两边的数合并的结果已经算出来了),

dp[l][r]=min(dp[l][k]+dp[k+1][r]+消耗);         复杂度n^3;

原文地址:https://www.cnblogs.com/smilesundream/p/5757566.html