zoukankan      html  css  js  c++  java
  • [LOJ2292] [THUSC2016] 成绩单

    题目链接

    LOJ:https://loj.ac/problem/2292

    洛谷:https://www.luogu.org/problemnew/show/P5336

    Solution

    区间( m dp),状态比较难想...为啥网上好多仙人说这题很蠢,可能是我太菜了吧

    (f[l][r])表示([l,r])消完的最小代价,(g[l][r][x][y])表示把([l,r])的值域消成([x,y])的最小代价。

    注意这题只需要大小关系,所以可以离散化。

    转移就很好办了,先转移(g),枚举(r)号元素删不删,然后在由(g)转移(f),具体看下代码注释吧。

    复杂度(O(n^5))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    
    #define pii pair<int,int >
    #define vec vector<int >
    
    #define pb push_back
    #define mp make_pair
    #define fr first
    #define sc second
    
    #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 
    
    const int maxn = 55;
    const int inf = 1e9;
    const lf eps = 1e-8;
    const int mod = 1e9+7;
    
    int f[55][55],g[55][55][55][55],v[maxn],t[maxn],n,a,b,m;
    
    void init() {   
        read(n),read(a),read(b);
        FOR(i,1,n) read(v[i]),t[i]=v[i];
        sort(t+1,t+n+1);m=unique(t+1,t+n+1)-t-1;
        FOR(i,1,n) v[i]=lower_bound(t+1,t+m+1,v[i])-t;
    }
    
    void chmin(int &x,int y) {if(x>y) x=y;}
    void chmax(int &x,int y) {if(x<y) x=y;}
    
    #define sqr(x) ((x)*(x))
    
    int main() {
        init();
        memset(f,63,sizeof f);
        memset(g,63,sizeof g);
        FOR(i,1,n) {
            f[i][i]=a;
            FOR(l,1,m) FOR(r,l,m)
                if(l<=v[i]&&v[i]<=r) g[i][i][l][r]=0;
                else g[i][i][l][r]=a;   //初值注意下
        }
        for(int len=2;len<=n;len++)
            for(int l=1;l<=n-len+1;l++) {
                int r=l+len-1;
                for(int x=1;x<=m;x++)
                    for(int y=x;y<=m;y++) {
                        if(x<=v[r]&&v[r]<=y) chmin(g[l][r][x][y],g[l][r-1][x][y]);   // 不删r
                        for(int k=l+1;k<=r;k++)
                            chmin(g[l][r][x][y],g[l][k-1][x][y]+f[k][r]);        // 删r,枚举包括r的区间
                        chmin(f[l][r],g[l][r][x][y]+a+b*sqr(t[y]-t[x]));      //转移f
                    }
            }
        write(f[1][n]);
        return 0;
    }
    
  • 相关阅读:
    【C/C++】最长公共子序列(LCS)/动态规划
    【C/C++】vector 动态二维数组
    【C/C++】string的长度
    【C/C++】最长不下降子序列/动态规划
    【C/C++】最大连续子序列和/动态规划
    【C/C++】输入:连续输入,以逗号隔开
    【C/C++】链表/ListNode/数据结构
    【Matlab】abs不支持复整数
    获取正在运行的服务
    从源码的角度分析Volley加载数据的过程
  • 原文地址:https://www.cnblogs.com/hbyer/p/10954068.html
Copyright © 2011-2022 走看看