JZOJ 5263. 【NOIP2017模拟8.12A组】分手是祝愿

来源:互联网 发布:mac axure 没响应 编辑:程序博客网 时间:2024/04/29 16:02

Description

Description

Input

Input

Output

Output

Sample Input

2
2
15 19
3
30 40 20

Sample Output

285
2600

Data Constraint

Data Constraint

Solution

  • 这题我用的是动态规划的解法(用类似分治的 DFS 过程实现)。

  • F[l][r] 表示将 [lr] 这段区间的材料全部合并、变成一份材料的最小花费。

  • 再设 G[l][r] 表示将 [lr] 这段区间的材料全部合并成一份材料其魔力值。

  • 那么递归时,若 F[l][r]>=0 ,说明之前已处理过这个区间,可以直接退出(记忆化)。

  • 否则我们枚举 ilir 分别递归 [l,i][i+1,r] 两个小区间,再合并大的区间。

  • 可以得出转移方程式:

    F[l][r]=Min{G[l][i]G[i+1][r]+F[l][i]+F[i+1][r]}

  • 若成功转移,则也要更新 G[l][r] 的值:

    g[l][r]=(g[l][i]+g[i+1][r])%100

  • 那么最终答案即为 F[1][N] ,时间复杂度 O(N3)

Code

#include<cstdio>#include<cstring>using namespace std;const int N=101;int f[N][N],g[N][N];inline int read(){    int X=0,w=1; char ch=0;    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();    return X*w;}inline int dfs(int l,int r){    if(f[l][r]>=0) return f[l][r];    for(int i=l;i<r;i++)    {        int x=dfs(l,i),y=dfs(i+1,r);        if(f[l][r]<0 || x+y+g[l][i]*g[i+1][r]<f[l][r])        {            f[l][r]=g[l][i]*g[i+1][r]+x+y;            g[l][r]=(g[l][i]+g[i+1][r])%(N-1);        }    }    return f[l][r];}int main(){    int T=read();    while(T--)    {        int n=read();        memset(f,-1,sizeof(f));        for(int i=1;i<=n;i++) g[i][i]=read(),f[i][i]=0;        printf("%d\n",dfs(1,n));    }    return 0;}
阅读全文
1 0