</pre>题目描述<p></p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:'microsoft yahei'; font-size:15.555556297302246px; line-height:35px">有一个矩形的由 X 和 . 组成的图像,已知它的长和宽。现在给你一个坐标(保证坐标上是X),求其整个连块的周长。(连块就是连着的X,斜着有相同顶点也算)。</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:'microsoft yahei'; font-size:15.555556297302246px; line-height:35px">输入长,宽,坐标X,坐标Y,接着是图。</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:'microsoft yahei'; font-size:15.555556297302246px; line-height:35px">多组数据,4个0结束。</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:'microsoft yahei'; font-size:15.555556297302246px; line-height:35px">样例</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:'microsoft yahei'; font-size:15.555556297302246px; line-height:35px">输入</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:'microsoft yahei'; font-size:15.555556297302246px; line-height:35px"></p><pre class="sio" name="code" style="white-space: pre-wrap; word-wrap: break-word; color: rgb(85, 85, 85); line-height: 35px; background-color: rgb(255, 255, 255); font-family: 'Courier New', Courier, monospace; font-size: 14px;">7 7 4 4
XXXXXXX
XX...XX
X..X..X
X..X...
X..X..X
X.....X
XXXXXXX
0 0 0 0
有个思路较好:要注意到周长的定义!,求一个连块的周长即找边界即可,从x开始搜,搜到一个外界的块那么周长加1,且做标记,可以用映射也可以用改动标志。
<pre name="code" class="cpp">#include<cstring> #include<iostream> #include<cstdio> using namespace std; char a[25][25]; int sx,sy; int cx,ry,sum=0; void dfs(int y,int x) { a[y][x]='!'; //改动标志来代替开一个数组加以映射。 for(int i=-1;i<=1;i++) for(int j=-1;j<=1;j++){ if(!i&&!j) continue; //去掉i=0且j=0(不移动)这一情况 if(a[y+i][x+j]=='X'&&1<=y+i&&y+i<=ry&&1<=x+j&&x+j<=cx) { dfs(y+i,x+j); } if((a[y+i][x+j]=='.'&&j==0)||(a[y+i][x+j]=='.'&&i==0)||(1>y+i&&j==0)||(y+i>ry&&j==0)||(x+j<1&&i==0)||(x+j>cx&&i==0)) { sum++; //找到正左正右正上正下有边界,则周长加一 } } } int main() { while(cin>>ry>>cx>>sy>>sx&&ry) { sum=0; memset(a,0,sizeof(a)); for(int i=1;i<=ry;i++) scanf("%s",a[i]+1); dfs(sy,sx); printf("%d\n",sum); } return 0; }
微微的思路:从给定坐标指向的X块向“深处”搜索。要求整个连通块的周长,不难发现和连通块中每个X的四周其他X的数量有关。若一个X上,下,左,右四个方向一个X都没有(因为斜着有相同顶点也算是连通,所以有这种情况的)那么这个X块对周长的贡献就是4。若有四周1个X,那么贡献就是3。四周2个X贡献2,四周3个X贡献1。若是四周全都是X,那么就自然没有贡献咯。最后输出总贡献就是周长了。
<pre name="code" class="cpp">#include <cstdio> #include <cstring> const int maxn = 21; char pic[maxn][maxn];//图像 int chek[maxn][maxn];//记录已经算过它周长的X块 int ans = 0;//记录周长 int chang,kuan;//图像的长宽 int chck(int x,int y)//不要看我先去看main函数 { if(x<0 || y<0 || x>=chang || y>=kuan) return 0;//如果这一点出界,返回0 if(pic[x][y] == '.') return 0;//如果这一点是.返回0 return 1;//最后肯定留下在界内的X,所以返回1 } void dfs(int x,int y)//不要看我先去看main函数 { if(x<0 || y<0 || x>=chang || y>=kuan) return;//如果出界,不考虑 if(pic[x][y] == '.' || chek[x][y] != 0) return;//如果它不是X,或者已经考虑过了,那么也不考虑 chek[x][y] = 1;//表示这一点已经考虑过了 int s = chck(x-1,y) + chck(x+1,y) + chck(x,y-1)+ chck(x,y+1);//chck函数是判断这一点是不是X,因为有可能出界,所以不要直接简单用if/*这里的check,可以综合一下,当初写check函数的时候就写成检查四个面是不是X的会更简便*/<span style="font-family: Consolas, 'Courier New', Courier, mono, serif;"> </span> if(s==3) ans+=1;//四周有3个X,贡献为1,下面同理 if(s==2) ans+=2; if(s==1) ans+=3; if(s==0) ans+=4; dfs(x-1,y+1);//四面八方扫一遍 dfs(x-1,y); dfs(x-1,y-1); dfs(x,y-1); dfs(x,y+1); dfs(x+1,y+1); dfs(x+1,y); dfs(x+1,y-1); /*上面的四面八方扫一遍也可以用循环实现,更简洁。 } int main() { while(scanf("%d%d",&chang,&kuan) &&chang&&kuan){//读入图像长和宽 memset(pic,0,sizeof(pic)); memset(chek,0,sizeof(chek));//切记切记初始化这里小心,因为一开始把初始化粗心放到while外面了WA了一发 ans = 0;//这也是初始化,周长置为0 int x,y;//坐标 scanf("%d%d",&x,&y);//读入坐标。注意这里实际指向的是pic[x-1][y-1]! for(int i = 0 ;i < chang ; i ++) scanf("%s",pic[i]);//读入整张图 dfs(x-1,y-1);//DFS思想,通俗说就是以这一点为源头把这个连块的所有X块都给揪出来。 printf("%d\n",ans);//输出最后的周长 } return 0; }注释真良心,感谢微微~
可见也可以用这种找规律的方法来写,找到周长的贡献度,不过这样会加大编写代码的思维难度。
当然也可以用BFS写 0ms:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
struct point
{
int x;
int y;
};
int col,row,sx,sy,ans=0;
bool book[25][25];
char a[25][25];
queue<point> que;
void ini()
{
memset(book,0,sizeof(book));
memset(a,0,sizeof(a));
while(!que.empty()) que.pop();
ans=0;
cin>>sx>>sy;
for(int i=1;i<=row;i++) scanf("%s",a[i]+1);
}
void bfs()
{
point temp;
temp.x=sx;
temp.y=sy;
book[sx][sy]=true;
que.push(temp);
while(que.size())
{
point temp=que.front();
point next;
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++){
if(!j&&!i) continue;
next.x=temp.x+i;
next.y=temp.y+j;
if(book[next.x][next.y]) continue;
if(!(i*j)&&(a[next.x][next.y]=='.'||next.x<1||next.x>row||next.y<1||next.y>col)) ans++;
if(a[next.x][next.y]=='X') {
que.push(next);
book[next.x][next.y]=1;
}
}
que.pop();
}
}
int main()
{
// freopen("1.in","r",stdin);
while(cin>>row>>col&&row)
{
ini();
bfs();
cout<<ans<<endl;
}
return 0;
}