zoukankan      html  css  js  c++  java
  • BZOJ 4897

    这题感觉真是太神了....

    看了网上很多题解,最后参考了这个:http://blog.csdn.net/hld67890/article/details/72556554

    首先我们容易想到区间DP,令DP[i][j]表示将[i,j]这段区间全部取完的最小代价,那么我们要如何转移呢?我们发现DP[i][j]的转移过程其实是在[i,j]中选一个子序列,然后我们将这个区间取成只剩这个子序列,然后再将这个子序列取走。这样我们就需要DP套DP,令fz[o][p1][p2]表示在[i,j]中考虑到了o这个数,最大值的位置在p1,最小值的位置在p2的方案数,那么这个DP的转移就是考虑一下o+1这个数,以及枚举子序列的间隔,间隔的代价我们已经得到了(因为[i,j]的子区间的DP值我们都已经算出了),这样fz数组也可以求出来了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define maxn 55
     6 const int INF=1000000000;
     7 int dp[maxn][maxn],fz[maxn][maxn][maxn];
     8 int n,a,b,w[maxn];
     9 
    10 void getdp(int l,int r)
    11 {
    12     for (int i=l;i<=r;i++)
    13         for (int j=l;j<=i;j++)
    14             for (int k=l;k<=i;k++)
    15                 fz[i][j][k]=INF;
    16     fz[l][l][l]=0;
    17     for (int i=l;i<=r;i++) 
    18     {
    19         fz[i][i][i]=min(fz[i][i][i],dp[l][i-1]);
    20         for (int j=l;j<=i;j++)
    21             for (int k=l;k<=i;k++)
    22             {
    23                 if (fz[i][j][k]==INF) continue;
    24                 int t1= w[j]>w[i+1]?j:i+1;
    25                 int t2= w[k]<w[i+1]?k:i+1;
    26                 fz[i+1][t1][t2]=min(fz[i][j][k],fz[i+1][t1][t2]);
    27                 for (int o=i+1;o<=r;o++)
    28                     fz[o][j][k]=min(fz[o][j][k],fz[i][j][k]+dp[i+1][o]);
    29             }
    30     }
    31 }
    32 
    33 int main()
    34 {
    35     scanf("%d",&n);
    36     scanf("%d%d",&a,&b);
    37     for (int i=1;i<=n;i++) scanf("%d",&w[i]);
    38     for (int len=1;len<=n;len++)
    39         for (int l=1;l+len-1<=n;l++)
    40         {
    41             int r=l+len-1;
    42             dp[l][r]=INF;
    43             getdp(l,r);
    44             for (int i=l;i<=r;i++)
    45                 for (int j=l;j<=r;j++) 
    46                 {
    47                     if (fz[r][i][j]==INF) continue;
    48                     dp[l][r]=min(dp[l][r],fz[r][i][j]+a+b*(w[i]-w[j])*(w[i]-w[j]));
    49                 }
    50         }
    51     printf("%d
    ",dp[1][n]);
    52     return 0;
    53 }
  • 相关阅读:
    Linux下Kafka单机安装配置
    MySQL30条规范解读
    MySQL联合索引最左匹配范例
    Percona Data Recovery Tool 单表恢复
    SQL中的where条件,在数据库中提取与应用浅析
    【leetcode】908. Smallest Range I
    【leetcode】909. Snakes and Ladders
    【leetcode】910. Smallest Range II
    【leetcode】395. Longest Substring with At Least K Repeating Characters
    【leetcode】907. Sum of Subarray Minimums
  • 原文地址:https://www.cnblogs.com/lvyouyw/p/6910252.html
Copyright © 2011-2022 走看看