[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);
围巾的剪裁条件如下:
裁成的两块小围巾形状与原来的大围巾完全相同,都是正三角形。
每一块小围巾里都不存在被蛀虫咬坏的部分。
裁剪时必须沿着单元的边界裁剪。
要求两块小围巾的面积的总和最大。
图中,最优的裁剪方法已经用粗线画了出来,面积和为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;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #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; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 用 C# 插值字符串处理器写一个 sscanf
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!