zoukankan      html  css  js  c++  java
  • loj 2292「THUSC 2016」成绩单

    loj

    看着就很区间dp,所以考虑求(f_{i,j})表示区间([i,j])的答案.注意到贡献答案的方式是每次选一个连续段,拿走后剩下的段拼起来继续段,所以转移就考虑从最后一次选的方法转移过来,那么最后一次选的是原序列的一个连续段中挖掉一些小连续段的一些段.设辅助状态(g_{i,j,p,q})表示区间([i,j])要选出一个连续段,其中最小值为(p),最大值为(q)的最小代价,转移可以在左右两边接上一个(f_{i,j})(这一段不在最终段中),或者接上一个在段内的元素,并更新最大值/最小值.最后用(g)更新(f),大概为(f_{i,j}=min(a+g_{i,j,p,q}+b(q-p)^2))

    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=55,mod=1e9+7;
    int rd()
    {
    	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^48);ch=getchar();}
    	return x*w;
    }
    int n,a,b,t,w[N],bb[N],f[N][N],g[N][N][N][N];
    
    int main()
    {
    	n=rd(),a=rd(),b=rd();
    	for(int i=1;i<=n;++i) w[i]=bb[i]=rd();
    	sort(bb+1,bb+n+1),t=unique(bb+1,bb+n+1)-bb-1;
    	for(int i=1;i<=n;++i) w[i]=lower_bound(bb+1,bb+t+1,w[i])-bb;
    	memset(f,0x3f3f3f,sizeof(f)),memset(g,0x3f3f3f,sizeof(g));
    	for(int i=1;i<=n;++i) f[i][i]=a,g[i][i][w[i]][w[i]]=0;
    	for(int i=1;i<=n;++i)
    	{
    		g[i-1][i][w[i]][w[i]]=min(g[i-1][i][w[i]][w[i]],g[i][i][w[i]][w[i]]+f[i-1][i-1]);
    		g[i][i+1][w[i]][w[i]]=min(g[i][i+1][w[i]][w[i]],g[i][i][w[i]][w[i]]+f[i+1][i+1]);
    		int np=min(w[i],w[i-1]),nq=max(w[i],w[i-1]);
    		g[i-1][i][np][nq]=min(g[i-1][i][np][nq],g[i][i][w[i]][w[i]]);
    		np=min(w[i],w[i+1]),nq=max(w[i],w[i+1]);
    		g[i][i+1][np][nq]=min(g[i][i+1][np][nq],g[i][i][w[i]][w[i]]);
    	}
    	for(int l=1;l<n;++l)
    		for(int i=1,j=l+1;j<=n;++i,++j)
    		{
    			for(int p=1;p<=t;++p)
    				for(int q=p;q<=t;++q)
    				{
    					for(int k=i;k<j;++k)
    						g[i][j][p][q]=min(g[i][j][p][q],min(g[i][k][p][q]+f[k+1][j],g[k+1][j][p][q]+f[i][k]));
    					int np=min(p,w[i-1]),nq=max(q,w[i-1]);
    					g[i-1][j][np][nq]=min(g[i-1][j][np][nq],g[i][j][p][q]);
    					np=min(p,w[j+1]),nq=max(q,w[j+1]);
    					g[i][j+1][np][nq]=min(g[i][j+1][np][nq],g[i][j][p][q]);
    					f[i][j]=min(f[i][j],a+g[i][j][p][q]+b*(bb[q]-bb[p])*(bb[q]-bb[p]));
    				}
    		}
    	printf("%d
    ",f[1][n]);
    	return 0;
    }
    
  • 相关阅读:
    ZOJ 2770 Burn the Linked Camp 差分约束
    作业04 一个简单的扑克牌游戏
    C++友元
    ZOJ 3645高斯消元
    CodeForces 55D 数位统计
    03类的设计和使用
    HDU 4522
    POJ 2559单调栈
    PL/SQL REPORT 开发模拟登陆
    修改报表心得
  • 原文地址:https://www.cnblogs.com/smyjr/p/11986403.html
Copyright © 2011-2022 走看看