题解 P6265 【[COCI2014/2015#3]SILUETA】
wuyonghuming
·
·
题解
思路:
这道题只要处理好几个重点就可以 AC 了
$2.$最下面的那一行应该全部输出"*"
$3.$在统计答案的时候,在地里面的也要加上去
## 代码:
```c
#include <stdio.h>//这道题我用的是C语言
int read()//快速读入,顺便说一下
{
int a=0;//一开始这个要返回的数是零
char b=getchar();//先取一个字符
while(b<'0'||b>'9')//如果还没到数字就是没用的
b=getchar();//一直取字符
while(b>=48&&b<=57)//当出现数字就代表是一个数
{
a=a*10+b-'0';//这个数乘上十再加上这个数字
b=getchar();//再取下一个字符
}
return a;//返回
}
int max(int a,int b)//手写最大值
{
if(a>b)//如果第一个数比第二个大
{
return a;//返回第一个
}
return b;//返回第二个
}
int min(int a,int b)//手写最小值
{
if(a<b)//如果第一个比第二个小
{
return a;//返回第一个
}
return b;//返回第二个
}
int s[1001];//这个数组记录每一列高楼的高度
int main()//主函数
{
int n=read(),ll=0x3f,rr=-0x3f,hh=-0x3f,ans=0;//把应该赋值的都赋一个初始值,0x3f是个常数
char m[1001][1001];//这个是将来的答案
for(int i=1;i<=n;i++)//循环输入每一幢大楼的样子
{
int l=read(),r=read(),h=read();//输入左边右边和高度
for(int j=l;j<=r-1;j++)//从左到右,这一列的最高高度要更新
{
s[j]=max(s[j],h);//更新最高高度
}
ll=min(l,ll);//更新最左边
rr=max(r-1,rr);//更新最右边
hh=max(h,hh);//更新最高高度
}
for(int i=ll;i<=rr;i++)//从左到右
{
for(int j=1;j<=hh;j++)//从地面到最高高度
{
m[i][j]='.';//在没建筑的情况下是空的
}
}
for(int i=ll;i<=rr;i++)//从左到右
{
for(int j=0;j<=hh;j++)//从下到上
{
if(((s[i+1]<=j||s[i-1]<=j)&&j<=s[i])||s[i]==j)//如果左边的高度小于现在高度或者右边高度小于现在高度或者到了最上面
{
ans++;//轮廓长度加一
m[i][j]='#';//这个点变成建筑覆盖
}
}
if(s[i]==0)//如果在地里而且这个点为空,上面的循环也会把答案加上去
{
ans--;//轮廓长度减一
}
}
printf("%d\n",ans);//输出轮廓长度
for(int i=hh;i>=1;i--)//因为高度才是行数,而且要倒过来
{
for(int j=ll;j<=rr;j++)//从左到右
{
putchar(m[j][i]);//输出答案
}
puts("");//下一行
}
for(int i=ll;i<=rr;i++)//从左到右
{
printf("*");//最下面应该是*
}
return 0;//别忘了
}
```
**谢谢管理审核和大家观赏,希望能看懂**