• [THUSC2016]成绩单 [区间dp]


    简单区间dp。

    考虑 (f_{i,j,mn,mx})表示 (i,j) 区间的最大值为 (mx),最小值为 (mn) 的最小花费,(g_{i,j}) 为删掉 ([i,j]) 的最小花费。目标答案:(g_{1,n})

    我们容易发现这个状态可以由区间 ([L,R-1])([R,R]) 合并起来,即加入一个 (v_r) ,第一个转移方程 (f_{i,j,min(mn,v_r),max(mx,v_r)} = min {f_{i,j-1,mn,mx}})

    我们还可以枚举断点 (k) , 把区间分成 ([L,k])([k+1,r])
    (f_{i,j,mn,mx} = min (f_{i,j,mn,mx},f_{i,k,mn,mx} + g_{k+1,r}))

    更新 (g_{l,r})

    枚举 (f_{l,r,mn,mx}) 最小值为 (mn),最小值为 (mx),模拟删去过程就好了。

    (g_{l,r} = min(f_{l,r,mn,mx}+a+b(mx-mn)^2))

    这题没了

    // powered by c++11
    // by Isaunoya
    #include<bits/stdc++.h>
    #define rep(i , x , y) for(register int i = (x) ; i <= (y) ; ++ i)
    #define Rep(i , x , y) for(register int i = (x) ; i >= (y) ; -- i)
    using namespace std ;
    using db = double ;
    using ll = long long ;
    using uint = unsigned int ;
    #define int long long
    using pii = pair < int , int > ;
    #define ve vector
    #define Tp template
    #define all(v) v.begin() , v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    #define fir first
    #define sec second
    // the cmin && cmax
    Tp < class T > void cmax(T & x , const T & y) {
    		if(x < y) x = y ;
    }
    Tp < class T > void cmin(T & x , const T & y) {
    		if(x > y) x = y ;
    }
    // sort , unique , reverse
    Tp < class T > void sort(ve < T > & v) {
    		sort(all(v)) ;
    }
    Tp < class T > void unique(ve < T > & v) {
    		sort(all(v)) ;
    		v.erase(unique(all(v)) , v.end()) ;
    }
    Tp < class T > void reverse(ve < T > & v) {
    		reverse(all(v)) ;
    }
    const int SZ = 0x191981 ;
    struct FILEIN {
    	~ FILEIN () {} char qwq[SZ] , * S = qwq , * T = qwq , ch ;
    	char GETC() {
    		return (S == T) && (T = (S = qwq) + fread(qwq , 1 , SZ , stdin) , S == T) ? EOF : * S ++ ;
    	}
    	FILEIN & operator >> (char & c) {
    		while(isspace(c = GETC())) ;
    		return * this ;
    	}
    	FILEIN & operator >> (string & s) {
    		while(isspace(ch = GETC())) ;
    		s = ch ;
    		while(! isspace(ch = GETC())) s += ch ;
    		return * this ;
    	}
    	Tp < class T > void read(T & x) {
    			bool sign = 1 ;
    			while((ch = GETC()) < 0x30) if(ch == 0x2d) sign = 0 ;
    			x = (ch ^ 0x30) ;
    			while((ch = GETC()) > 0x2f) x = x * 0xa + (ch ^ 0x30) ;
    			x = sign ? x : -x ;
    	}
    	FILEIN & operator >> (int & x) {
    		return read(x) , * this ;
    	}
    	FILEIN & operator >> (signed & x) {
    		return read(x) , * this ;
    	}
    	FILEIN & operator >> (unsigned & x) {
    		return read(x) , * this ;
    	}
    } in ;
    struct FILEOUT {
    	const static int LIMIT = 0x114514 ;
    	char quq[SZ] , ST[0x114] ;
    	signed sz , O ;
    	~ FILEOUT () {
    		sz = O = 0 ;
    	}
    	void flush() {
    		fwrite(quq , 1 , O , stdout) ;
    		fflush(stdout) ;
    		O = 0 ;
    	}
    	FILEOUT & operator << (char c) {
    		return quq[O ++] = c , * this ;
    	}
    	FILEOUT & operator << (string str) {
    		if(O > LIMIT) flush() ;
    		for(char c : str) quq[O ++] = c ;
    		return * this ;
    	}
    	Tp < class T > void write(T x) {
    			if(O > LIMIT) flush() ;
    			if(x < 0) {
    				quq[O ++] = 0x2d ;
    				x = -x ;
    			}
    			do {
    				ST[++ sz] = x % 0xa ^ 0x30 ;
    				x /= 0xa ;
    			} while(x) ;
    			while(sz) quq[O ++] = ST[sz --] ;
    			return ;
    	}
    	FILEOUT & operator << (int x) {
    		return write(x) , * this ;
    	}
    	FILEOUT & operator << (signed x) {
    		return write(x) , * this ;
    	}
    	FILEOUT & operator << (unsigned x) {
    		return write(x) , * this ;
    	}
    } out ;
    
    int n , a , b ;
    const int maxn = 52 ;
    int f[maxn][maxn][maxn][maxn] ;
    int g[maxn][maxn] ;
    signed main() {
    #ifdef _WIN64
    	freopen("testdata.in" , "r" , stdin) ;
    #else
    	ios_base :: sync_with_stdio(false) ;
    	cin.tie(nullptr) , cout.tie(nullptr) ;
    #endif
    // code begin.
    	in >> n >> a >> b ;
    	vector < int > v(n) , c(n) ;
    	for(int i = 0 ; i < n ; i ++) {
    		in >> v[i] ;
    		c[i] = v[i] ;
    	}
    	unique(c) ; int siz = sz(c) ;
    	memset(f , 0x3f , sizeof(f)) ;
    	memset(g , 0x3f , sizeof(g)) ; 
    	for(int i = 0 ; i < n ; i ++) {
    		v[i] = lower_bound(all(c) , v[i]) - c.begin() ;
    		f[i][i][v[i]][v[i]] = 0 ;
    		g[i][i] = a ;
    	}
    	for(int len = 1 ; len <= n ; len ++) {
    		for(int l = 0 ; l + len - 1 < n ; l ++) {
    			int r = l + len - 1 ;
    			
    			for(int mn = 0 ; mn < siz ; mn ++)
    				for(int mx = mn ; mx < siz ; mx ++)
    					cmin(f[l][r][min(mn , v[r])][max(mx , v[r])] , f[l][r - 1][mn][mx]) ;
    					
    			for(int k = l ; k < r ; k ++)
    				for(int mn = 0 ; mn < siz ; mn ++)
    					for(int mx = mn ; mx < siz ; mx ++)
    						cmin(f[l][r][mn][mx] , f[l][k][mn][mx] + g[k + 1][r]) ;
    						
    			for(int mn = 0 ; mn < siz ; mn ++)
    				for(int mx = mn ; mx < siz ; mx ++)
    					cmin(g[l][r] , f[l][r][mn][mx] + a + b * (c[mx] - c[mn]) * (c[mx] - c[mn])) ;
    					
    		}
    	}
    	out << g[0][n - 1] << '
    ' ;
    	return out.flush() , 0 ;
    // code end.
    }
    
  • 相关阅读:
    python学习第三天
    python学习第二天
    如何解决自学编程的犯困问题
    python学习计划第四天-python第一天
    python学习第三天-Linux入门之二
    python第二天-Linux基础学习
    python入门第一天-Linux的学习入门
    Linux下gdb的使用
    整理一下常见的十种排序
    对指针的理解
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12267334.html
Copyright © 2020-2023  润新知