zoukankan      html  css  js  c++  java
  • 成绩单

    满分做法:

    这个状态是我见到过最奇怪的,(f[i][j][l][r])表示在区间([i,j])中取出一些数后,剩下的数值在([l,r])范围内的最小代价。因为(w[i]<=1000),这个显然不能存在作为数组下标,所以离散化就好了。

    由这个状态可知(f[i][j][0][0])就是将这一段全部取完的最小代价。

    考虑转移:

    (l,r)离散前的数为(x,y)。对于(f[i][j][0][0])的转移有两种情况:

    1.一次全部取完:(f[i][j][0][0])=(a)+(b)*((wi)(wj)的最大值-(wi)(wj)的最小值)²。

    2.先取完不在([l,r])内的数,剩下的一次取完:(f[i][j][0][0]=f[i][j][l][r]+a+b*(y-x)²),两者取最小值即可。

    对于(f[i][j][l][r])的转移,考虑枚举断点(k),则转移有三种情况:

    1.左边取完,右边没取完:(f[i][j][l][r]=f[i][k][0][0]+f[k+1][j][l][r])

    2.左边没取完,右边取完:(f[i][j][l][r]=f[i][k][l][r]+f[k+1][j][0][0])

    3.左边没取完,右边没取完:(f[i][j][l][r]=f[i][k][l][r]+f[k+1][j][l][r])

    对于其他情况:当(i==j)(l<=w[i]<=r)时,(f[i][j][l][r]=0),其他全赋成无穷大。

    因为转移的情况会有重复,所以记忆化搜索是一个不错的选择;此外因为搜索时都是区间区间的搜,保证取数是连续的。

    #include<cstring>
    #include<queue>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxm=57;
    const int inf=1e9+7;
    int n,a,b,tot;
    int w[maxm];
    int f[maxm][maxm][maxm][maxm];//f[i][j][l][r]表示在区间[i,j]中取出一些数后,剩下的数值在[l,r]范围内的最小代价
    int book[maxm],c[maxm];
    bool vis[maxm][maxm][maxm][maxm];
    int dfs(int i,int j,int l,int r)//记忆化搜索
    {
     if(vis[i][j][l][r]) return f[i][j][l][r];
     vis[i][j][l][r]=1;
     f[i][j][l][r]=inf;
     if(l==0&&r==0)
     {
       int x=inf,y=-inf;
       for(int k=i;k<=j;k++)
       {
         x=min(x,c[k]);
         y=max(y,c[k]);
       }
       f[i][j][0][0]=min(f[i][j][0][0],a+b*(y-x)*(y-x));//一次取空 
       for(int k=1;k<=tot;k++)
       {
       	 for(int p=k;p<=tot;p++)
    	 {
    	  f[i][j][0][0]=min(f[i][j][0][0],dfs(i,j,k,p)+a+b*(book[p]-book[k])*(book[p]-book[k]));//先取完不在l-r的数,在一次取完 
         }
       }
       return f[i][j][0][0];
     }
     else
     {
       if(i==j)
       {
        if(w[i]>=l&&w[i]<=r)
        f[i][j][l][r]=0;
        return f[i][j][l][r];//如果不是0,就是inf 
       }
       for(int k=i;k<=j-1;k++)
       {
         f[i][j][l][r]=min(f[i][j][l][r],dfs(i,k,0,0)+dfs(k+1,j,l,r));//左边取空 
         f[i][j][l][r]=min(f[i][j][l][r],dfs(i,k,l,r)+dfs(k+1,j,0,0));//右边取空 
         f[i][j][l][r]=min(f[i][j][l][r],dfs(i,k,l,r)+dfs(k+1,j,l,r));//左右均取不完 
       }
       return f[i][j][l][r];
     }
    }
    int main()
    {
     scanf("%d%d%d",&n,&a,&b);
     for(int i=1;i<=n;i++)
     {
      scanf("%d",c+i); 
      book[i]=c[i];
     }
     sort(book+1,book+n+1);
     tot=unique(book+1,book+n+1)-book-1;
     for(int i=1;i<=n;i++)
     {
      w[i]=lower_bound(book+1,book+tot+1,c[i])-book;	
     }
     printf("%d
    ",dfs(1,n,0,0));
     return 0;	
    }
    
  • 相关阅读:
    triangle
    Synchronizing timer
    jenkins 安装网址
    Java I/O编程思路
    SpEL快速入门
    Spring ApplicationContext的事件机制
    畅谈Spring设计哲学
    Spring ApplicationContext的国际化支持
    SQL中 WHERE与HAVING的区别
    Hibernate的查询语言之HQL(二)——Hibernate查询的from字句
  • 原文地址:https://www.cnblogs.com/lihan123/p/11712461.html
Copyright © 2011-2022 走看看