• [NOI1998]:围巾裁剪


    裁缝有一块非常珍贵的丝绸围巾。可惜的是,围巾的某些部分已经被蛀虫给咬坏了。裁缝当然不愿意就这么把围巾给丢了,于是,他想把围巾给裁成两块小围巾送给他的两个女儿。自然,两块小围巾的面积之和越大越好。 
    这块围巾是一个正三角形,三条边被均匀地分成了N段,即这个正三角形被均匀地分成了N2个单元,每个单元是一个面积为1的正三角形。图一所 示为一个N=5的围巾,图中带阴影的单元表示被蛀虫咬坏的部分。从上往下看,围巾被分成了N行,第一行有1个单元,第二行有3个单元,其中有2个是形如D 的,有1个是形如Ñ 的(这两种三角形我们认为是形状相同的)。第三行有5个,其中有3个是形如D 的,有2个是形如Ñ 的…… 。用坐标(X,Y)给每个单元定位,第一行的单元的坐标为(1,1);第二行从左到右的三个单元的坐标依次为(2,1)、(2,2)、(2,3);

    pic

    围巾的剪裁条件如下: 
    裁成的两块小围巾形状与原来的大围巾完全相同,都是正三角形。 
    每一块小围巾里都不存在被蛀虫咬坏的部分。 
    裁剪时必须沿着单元的边界裁剪。 
    要求两块小围巾的面积的总和最大。 
    图中,最优的裁剪方法已经用粗线画了出来,面积和为4+9=13。 
    现在需要你编一个程序来帮助裁缝解决这个问题。

    Input

    第一行为一个整数N(1<=N<=100),表示这块围巾总共被分成了N2个单元。第二行为一个整数M(0<= M<=N2-2),表示这块围巾共有M个单元被蛀虫咬坏了。 
    接下的M行,每一行有两个正整数X和Y,为这M个被蛀虫咬坏的单元的坐标。 
    输入文件中同一行相邻两项之间用一个或多个空格隔开。

    Output

    仅含一个整数,为你所找到的裁出两块小围巾面积总和的最大值。z

    SS:用DP的方法;DP出每个小正三角形能延伸多少层,枚举割线,分成小三角形和梯形,取ans的最大值再旋转120度,循环3次继续DP下去

    DP方程很好想到,a[i][2*j-1]=min(a[i+1][2*j-1],a[i+1][2*j+1])+1,
       a[i][2*j]=min(a[i-1][2*j],a[i-1][2*(j-1)])+1;
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n,x,y,m,ans;
    int a[10001][20001];
    int b[10001][20001];
    void make(){
    	for(int i=1;i<=n;++i)if(a[n][i*2-1]!=-1)a[n][i*2-1]=1;
    	for(int i=n-1;i>=1;--i)
    	for(int j=1;j<=i;++j)if(a[i][2*j-1]!=-1){
    		a[i][2*j-1]=1;
    		if(a[i+1][2*j-1]!=-1&&a[i+1][2*j]!=-1&&a[i+1][2*j+1]!=-1)
    		a[i][2*j-1]=min(a[i+1][2*j-1],a[i+1][2*j+1])+1;
    	}
    	for(int i=2;i<=n;++i)
    	for(int j=1;j<=i-1;++j)if(a[i][2*j]!=-1){
    		a[i][2*j]=1;
    		if(j!=1&&j!=i-1&&a[i-1][2*(j-1)+1]!=-1&&a[i-1][2*(j-1)]!=-1&&a[i-1][2*j]!=-1)
    		a[i][2*j]=min(a[i-1][2*(j-1)],a[i-1][2*j])+1;
    	}
    }
    void ask(){
    	int max1,max2;
    	for(int i=1;i<n;++i){//枚举分割线 
    		max1=0,max2=0;
    		for(int j=1;j<=i;++j){
    			for(int k=1;k<=j;++k)max1=max(min(i-j+1,a[j][k*2-1]),max1);
    			for(int k=1;k<=j-1;++k)max1=max(a[j][k*2],max1);
    		}
    		for(int j=i+1;j<=n;++j){
    			for(int k=1;k<=j;++k)max2=max(a[j][k*2-1],max2);
    			for(int k=1;k<=j-1;++k)max2=max(max2,min(j-i,a[j][k*2]));
    		}
    		if(max1!=0&&max2!=0)ans=max(ans,max1*max1+max2*max2);
    	}
    }
    void splay(){
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=i;++j)
    		if(a[i][2*j-1]==-1)b[n-i+j][(n-i)*2+1]=-1;
    		for(int j=1;j<=i-1;++j)if(a[i][2*j]==-1)b[n-i+j+1][(n-i)*2+2]=-1;
    	}
    	for(int i=1;i<=n;++i)
    	 for(int j=1;j<=2*i-1;++j)a[i][j]=b[i][j];
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;++i)scanf("%d%d",&x,&y),a[x][y]=-1;
    	for(int tt=1;tt<=3;++tt){
    		make();ask();
    		memset(b,0,sizeof(b));
    		splay();
    	}
    	printf("%d",ans);
    	return 0;
    }
    

  • 相关阅读:
    无文件攻击形式——在注册表中保存加密数据,注入代码到正在运行的进程,并使用PowerShell、Windows Management Instrumentation和其他技术使其难以被检测以及分析。
    2020年无文件攻击技术的新型勒索病毒专题分析报告——亚信安全
    挖矿木马简要技术分析
    腾讯2020挖矿木马报告
    根目录被赋予777 R权限后的处理过程
    服务器性能参数学习与总结
    信创迁移适配实战SpringBoot项目打包war部署至TongWeb7 规格严格
    SpringBoot集成MinIO实践 规格严格
    致命错误: 在类路径或引导类路径中找不到程序包 java.lang 规格严格
    python命令行解析 规格严格
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6501179.html
Copyright © 2020-2023  润新知