zoukankan      html  css  js  c++  java
  • 【uoj125】 NOI2013—书法家

    http://uoj.ac/problem/125 (题目链接)

    题意

      在网格上写“NOI”,每个格子上有一些权值,要求覆盖的权值最大。书写有一些规则。

    Solution

      将“NOI”分成11个部分,每个部分都是有几个有相同特点的矩形构成的,按列dp前缀最大值优化一下即可。看起来很难码的样子,其实套路都差不多,但是想清楚,一些细节处理到位,平时习惯好一点就可以很快写完辣。

      ${f[p][i][j][k]}$表示第${p}$个部分,正在dp第${i}$列,矩形上边界为${j}$,下边界为${k}$时,最大权值。

      ${mx[p][i][j][k]}$表示的是第${p}$个部分,第${i}$列,与上边界${j}$,下边界${k}$相关的前缀最大值。

      其实比较恶心的就是第二部分,你需要处理出这样的一个前缀最大值:上边界的区间在${[1,j]}$,下边界的区间在${[j+1,k]}$。这个并不好直接求出来,所以我们把它分成两部分:上边界区间在${[1,j]}$,下边界固定在${j+1}$;以及上边界在${[1,j]}$,下边界在${[j,k]}$。这样就非常好处理了。

      第${i}$列那一维再滚动一下就好了。

    细节

      初始化什么的。然后${j,k}$按照它们的意义${for}$过去可能会清晰一些吧。

    代码

    // uoj125
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #define LL long long
    #define inf (1ll<<30)
    #define MOD 1000000007
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=160,maxm=510;
    int a[maxn][maxm],s[maxm][maxn],up[maxn];
    int f[12][maxn][maxn],g[12][maxn][maxn],mx[12][maxn][maxn];
    int n,m;
    
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
    	for (int j=1;j<=m;j++)
    		for (int i=1;i<=n;i++) s[j][i]=s[j][i-1]+a[i][j];
    	for (int i=0;i<=11;i++)
    		for (int j=0;j<=n+1;j++)
    			for (int k=0;k<=n+1;k++) f[i][j][k]=g[i][j][k]=mx[i][j][k]=-inf;
    	for (int i=0;i<=n+1;i++) up[i]=-inf;
    	int ans=-inf;
    	for (int i=1;i<=m;i++) {
    		//第1部分
    		for (int j=1;j<=n;j++)
    			for (int k=j;k<=n;k++)
    				f[1][j][k]=max(g[1][j][k],0)+s[i][k]-s[i][j-1];
    		//第2部分
    		for (int j=1;j<=n;j++)
    			for (int k=n;k>=j;k--) mx[1][j][k]=max(g[1][j][k],mx[1][j][k+1]);
    		for (int k=1;k<=n;k++) {
    			up[k]=-inf;
    			for (int j=1;j<=k;j++) up[k]=max(up[k],g[2][j][k]);
    		}
    		for (int k=1;k<=n;k++)
    			for (int j=1;j<=k;j++) mx[2][j][k]=max(mx[2][j-1][k],g[2][j][k]);
    		for (int j=1;j<=n;j++)
    			for (int k=j;k<=n;k++) mx[2][j][k]=max(mx[2][j][k-1],mx[2][j][k]);
    		for (int j=1;j<=n;j++)
    			for (int k=j;k<=n;k++)
    				f[2][j][k]=max(up[j-1],max(mx[1][j][k+1],mx[2][j][k]))+s[i][k]-s[i][j-1];
    		//第3部分
    		for (int k=1;k<=n;k++)
    			for (int j=k;j>=1;j--) mx[2][j][k]=max(mx[2][j+1][k],g[2][j][k]);
    		for (int j=1;j<=n;j++)
    			for (int k=j;k<=n;k++)
    				f[3][j][k]=max(g[3][j][k],mx[2][j+1][k])+s[i][k]-s[i][j-1];
    		//第4部分
    		f[4][0][0]=g[4][0][0];
    		for (int j=1;j<=n;j++)
    			for (int k=j;k<=n;k++) f[4][0][0]=max(f[4][0][0],g[3][j][k]);
    		//第5部分
    		for (int j=1;j<=n;j++)
    			for (int k=j+2;k<=n;k++) f[5][j][k]=g[4][0][0]+s[i][k]-s[i][j-1];
    		//第6部分
    		for (int j=1;j<=n;j++)
    			for (int k=j+2;k<=n;k++) f[6][j][k]=max(g[5][j][k],g[6][j][k])+s[i][j]-s[i][j-1]+s[i][k]-s[i][k-1];
    		//第7部分
    		for (int j=1;j<=n;j++)
    			for (int k=j+2;k<=n;k++) f[7][j][k]=g[6][j][k]+s[i][k]-s[i][j-1];
    		//第8部分
    		f[8][0][0]=g[8][0][0];
    		for (int j=1;j<=n;j++)
    			for (int k=j+2;k<=n;k++) f[8][0][0]=max(f[8][0][0],g[7][j][k]);
    		//第9部分
    		for (int j=1;j<=n;j++)
    			for (int k=j+2;k<=n;k++) f[9][j][k]=max(g[9][j][k],g[8][0][0])+s[i][j]-s[i][j-1]+s[i][k]-s[i][k-1];
    		//第10部分
    		for (int j=1;j<=n;j++)
    			for (int k=j+2;k<=n;k++) f[10][j][k]=max(g[10][j][k],g[9][j][k])+s[i][k]-s[i][j-1];
    		//第11部分
    		for (int j=1;j<=n;j++)
    			for (int k=j+2;k<=n;k++) {
    				f[11][j][k]=max(g[10][j][k],g[11][j][k])+s[i][j]-s[i][j-1]+s[i][k]-s[i][k-1];
    				ans=max(ans,f[11][j][k]);
    			}
    		//滚动
    		for (int j=1;j<=11;j++)
    			for (int k=0;k<=n;k++)
    				for (int l=0;l<=n;l++) g[j][k][l]=f[j][k][l];
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    在App_Data中创建数据库获取连接串简便方法!
    ObjectDataSource配合存储过程(采用数据集)的使用(删除可以解决,但是编辑出错好像它的方法也无法解决
    金鹰dreamweaver视频教程下载地址
    ASP.NET里创建Microsoft Word文档
    net3:Calendar控件的使用
    vs2005做的留言本——天轰川下载
    Wiley出版 SQL Server 2005宝典
    ADO:防止更新的数据含有单引号而出错
    用 Bitcron 搭博客:你只管写作,它负责呈现
    如何去掉Myeclipse对JS等文件的验证
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6395082.html
Copyright © 2011-2022 走看看