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;
    }
    
  • 相关阅读:
    php 处理并发问题
    phpstudy 版本切换注意的问题
    php读取文件内容的三种方法
    防止重复提交表单的两种方法
    php 压缩函数gzencode gzdeflate gzcompress
    回调函数解析
    回调函数
    如何卸载红蜘蛛
    无法启动此程序,因为计算机中丢失MSVCR110.dll的解决方法
    mysql 去除重复 Select中DISTINCT关键字的用法
  • 原文地址:https://www.cnblogs.com/smyjr/p/11986403.html
Copyright © 2011-2022 走看看