原题
https://paiza.jp/botchi/challenges/botchi_a_1001
翻译(原贴:https://iobaka.com/blog/98.html)
你这次开始设计村庄规划了。
村庄南北向为 H ,东西向为 W ,总计 H × W 个格子。
假设给每个格子分配一个坐标,就如图1所示。
然后会列给你一个村庄建筑清单。
每栋建筑物都是矩形形状,并且有一个门。
门的位置不会是矩形的四个顶点。
就如图2所示。
由于建筑清单里有很多建筑物,所以并不是所有建筑全部都能建造在村子里。
所以你需要决定村子里需要建哪些建筑。
在决定建筑物的建筑地点时,需要遵守以下3点:
1.任何两个建筑物,不允许重叠
2.建筑物建筑方向需要和清单里给的一样,不许旋转放置建筑物。
3.任何两个建筑物,可以通过没有建筑的方块,和建筑物的门之间移动。
规则3如图3所示,
灰色建筑物和绿色建筑物之间,可以通过没有建筑的方块,以两个建筑物的门为起点和终点,进行移动。
而蓝色建筑物,则和其他两个建筑物之间没有移动方法,所以蓝色建筑物不满足规则3。
这个村子每个格子的建筑物可以产生1万日元的利润,
请编写一个程序,计算建筑物的放置位置,尽可能多的产生利润。
至少放置一个能产生利润的建筑物,就判定为正确答案,并根据利润计算得分。
(需要注意的是:1.建筑的门前至少有一个格子 2.建筑的门不会在建筑的四个顶点位置)
单个放的方法
原贴的老哥提出了一种单个放可以水过的想法,但是无奈都用PHP我是太蒟蒻看不懂,我就自己用c++模拟了一下单个放的方法
实际上第一步还是得去除特殊的情况
也就是说如果这个建筑物的面积大于地图的面积那么肯定得去除
然后就是分四种门的位置进行一波放置即可
分为在上面在下面在左面在右面,题目中明确提出不会出现在四个顶角所以if起来比较容易
我这个做法实际上有bug如果建筑物的面积等于地图的面积那么我这么放是放不进去的,不过数据并没有卡这个地方
代码
#include <bits/stdc++.h>
using namespace std;
int bk[666][666];
struct node
{
int h,w,x,y,id;
}num[666];
bool cmp(node a,node b)
{
return a.h*a.w>b.h*b.w;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,m,t,p=0;
cin>>n>>m>>t;
int now=n*m,minx=1,miny=1;
for(int i=1;i<=t;i++)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
if(a>0&&a<=n&&b>0&&b<=m)
num[p++]=(node){a,b,c,d,i};
}
sort(num,num+p,cmp);
int maxx=0;
maxx+=num[0].h;
int maxy=0;
maxy+=num[0].w;
if(num[0].x==1)
{
maxx++;minx++;
for(int j=minx;j<=maxx;j++)
for(int k=miny;k<=maxy;k++)
bk[j][k]=num[0].id;
}
else if(num[0].x==num[0].h)
{
for(int j=minx;j<=maxx;j++)
for(int k=miny;k<=maxy;k++)
bk[j][k]=num[0].id;
}
else if(num[0].y==1)
{
miny++;maxy++;
for(int j=minx;j<=maxx;j++)
for(int k=miny;k<=maxy;k++)
bk[j][k]=num[0].id;
}
else if(num[0].y==num[0].w)
{
for(int j=minx;j<=maxx;j++)
for(int k=miny;k<=maxy;k++)
bk[j][k]=num[0].id;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cout<<bk[i][j];
if(j<m)
cout<<" ";
}
cout<<"
";
}
}